当前位置: 首页 > article >正文

秋招突击——9/10、9\11——算法练习——携程笔试练习——2024年秋招第一批笔试

文章目录

    • 引言
    • 笔试准备
      • 2024年秋招研发第一批
        • 第一题
        • 第二题
          • 第二次实现
        • 第三题
        • 第四题
        • 第五题
          • 参考实现
    • 总结

引言

  • 准备全力冲携程,好好做算法,去线下面试!
  • 今天就好好做做携程往年的笔试!

笔试准备

2024年秋招研发第一批

第一题

在这里插入图片描述

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息

public class Main {
    public static boolean isPrime(int n) {
        for (int i = 2; i <= Math.sqrt(n); i ++) {
            if (n % i == 0)  return false;
        }
        return true;
    }

    static int res;
    static boolean[] visited;
    public static void dfs(int n, int idx, List<Integer> temp) {
        if (idx == n) {
            // 已经到达了终点,直接添加对应的元素
            res ++;
           // System.out.println(temp.toString());
            return;
        }

        for (int i = 1; i <= n; i ++) {
            if (!visited[i]) {
                // 没有访问过
                if (temp.isEmpty() || !isPrime(i  + temp.get(temp.size() - 1))) {
                    visited[i] = true;
                    temp.add(i);
                    dfs(n, idx + 1, temp);
                    temp.remove(temp.size() - 1);
                    visited[i] = false;
                }
            }
        }
    }


    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int n = in.nextInt();
            visited = new boolean[n + 1];
            dfs(n, 0, new ArrayList<Integer>());
            System.out.println(res);
        }
    }
}

总结

  • 明明是一个dfs,还是比较简单的dfs,但是有很多细节没注意到位,很难受!

在这里插入图片描述

第二题

在这里插入图片描述
在这里插入图片描述

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    public static boolean judge(int[] a,int[] b,int[] c) {
        // 判断是否为对应符合条件的三个点
        if((a[0] == b[0] && a[1] == c[1]) || (a[0] ==c[0] && a[1] == b[1])) return true;
        if((b[0] == a[0] && b[1] == c[1]) || (b[0] ==c[0] && b[1] == a[1])) return true;
        if((c[0] == b[0] && c[1] == a[1]) || (c[0] ==a[0] && c[1] == b[1])) return true;
        return false;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int m = in.nextInt();
            int n = in.nextInt();
            char[][] chars = new char[m][n];
            List<int[]> listY = new ArrayList<>();
            List<int[]> listO = new ArrayList<>();
            List<int[]> listU = new ArrayList<>();

            for(int i = 0;i < m;i ++){
                String str = in.next();
                chars[i] = str.toCharArray();
                for(int j = 0;j < chars[i].length;j ++){
                    if(chars[i][j] == 'y') listY.add(new int[]{i,j});
                    if(chars[i][j] == 'o') listO.add(new int[]{i,j});
                    if(chars[i][j] == 'u') listU.add(new int[]{i,j});

                }
            }

            // 开始具体的逻辑处理
            int count = 0;
            for(int[] pointY : listY){
                for(int[] pointO:listO){
                    for(int[] pointU:listU){
                        if(judge(pointY,pointO,pointU)) {
                            count ++;
                        }
                    }
                }
            }
            System.out.println(count );
        }
    }
}

在这里插入图片描述
总结

  • 仅仅通过三组,这里直接暴力,可以使用dp做一下,下次再试试看,因为每一个中心点,都要记录一下之前有多少u、o和y,明天再做
第二次实现
  • 计算每一行或者每一列的前n项的y、o、u的累加和,然后在计算乘积就行了!
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    public static boolean judge(int[] a, int[] b, int[] c) {
        // 判断是否为对应符合条件的三个点
        if ((a[0] == b[0] && a[1] == c[1]) || (a[0] == c[0] &&
                                               a[1] == b[1])) return true;
        if ((b[0] == a[0] && b[1] == c[1]) || (b[0] == c[0] &&
                                               b[1] == a[1])) return true;
        if ((c[0] == b[0] && c[1] == a[1]) || (c[0] == a[0] &&
                                               c[1] == b[1])) return true;
        return false;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int m = in.nextInt();
            int n = in.nextInt();
            char[][] chars = new char[m][n];
            int[][] rowCount = new int[m][3];  // 0表示y,1表示o,2表示u
            int[][] colCount = new int[n][3];  // 0表示y,1表示o,2表示u

            // 这个是遍历的标签
            for (int i = 0; i < m; i ++) {
                String str = in.next();
                chars[i] = str.toCharArray();
                for (int j = 0; j < chars[i].length; j ++) {
                    if (chars[i][j] == 'y') {
                        rowCount[i][0] ++;
                        colCount[j][0] ++;
                    }
                    if (chars[i][j] == 'o') {
                        rowCount[i][1] ++;
                        colCount[j][1] ++;
                    }
                    if (chars[i][j] == 'u') {
                        rowCount[i][2] ++;
                        colCount[j][2] ++;
                    }
                }
            }

            // 开始具体的逻辑处理
            long count = 0;
            for (int i = 0; i < m; i ++) {
                for (int j = 0; j < n; j ++) {
                    if (chars[i][j] == 'y') {
                        count = count + rowCount[i][1] * colCount[j][2] + rowCount[i][2] *
                                colCount[j][1] ;
                    }
                    if (chars[i][j] == 'o') {
                        count = count + rowCount[i][0] * colCount[j][2] + rowCount[i][2] *
                                colCount[j][0] ;

                    }
                    if (chars[i][j] == 'u') {
                        count = count + rowCount[i][1] * colCount[j][0] + rowCount[i][0] *
                                colCount[j][1] ;
                    }
                }
            }
            System.out.println(count );
        }
    }
}

在这里插入图片描述

第三题
  • 编写一个SQL查询,返回每个商品的销售总量,先按照商品类别升序排序,再按销售总量降序排列,同时包括商品名称和销售总量。此外,还需要在结果中包含每个商品在其所属类别内的排名,排名相同的商品可以按照 product_id 升序排序。

初始版本

  • 这个题目一开始只能写成下面那个初始化的版本,并不知道怎么在同一类别中再进行排名。
SELECT products.name as product_name, sum(quantity) as total_sales , products.category as category_rank
FROM orders
    join products on products.product_id = orders.product_id 
group by products.name , products.category ,orders.product_id;

最终版本

SELECT
    products.name as product_name,
    SUM(orders.quantity) AS total_sales,
    RANK() OVER (
        PARTITION BY
            products.category
        ORDER BY
            SUM(orders.quantity) DESC,
            products.product_id ASC
    ) AS category_rank
FROM
    products
    JOIN orders ON products.product_id = orders.product_id
GROUP BY
    products.name,
    products.category,
    products.product_id
ORDER BY
    products.category ASC,
    total_sales DESC,
    products.product_id ASC;

复习的知识

  • Rank关键字
    • 用来给结果集中的每一行分配一个排名,通过over来确定排名如何运用。
    • 需要使用order by来指定排名顺序
      在这里插入图片描述
  • 通过partion by将数据进行分组,然后按组内的数据进行排名。上述要求中,是按照同类别的销售总量进行的排序,所以需要增加一个partion by关键字

 rank() over (
        partition by products.category 
        order by sum(quantity) DESC , products.product_id ASC) as category_rank
第四题

在这里插入图片描述

个人实现

  • 无限次加一和减一操作,总量sum是不变的,直接计算一下平均值,看看能不能范围内,借此判定是否可以操作。然后计算所有小于左边界差值的累加和以及所有大于右边界的差值的累加和,然后选一个最大值就行了!
  • 这个代码写的很快,但是剩下的样例不知道怎么过了,感觉没啥问题!
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int T = in.nextInt();
        while (T-- > 0) { // 注意 while 处理多个 case
            int n = in.nextInt();
            int l = in.nextInt();
            int r = in.nextInt();
            int[] nums = new int[n];
            long sum = 0L;
            for(int i = 0;i < n;i ++)   {
                nums[i] = in.nextInt();
                sum += nums[i];
            }
            long avg = (long)sum / n;
            if(avg > r || avg < l)  System.out.println(-1);
            else{
                long subCount = 0;
                long addCount = 0;
                for(int x:nums){
                    if(x < l)   addCount += (l - x);
                    if(x > r)   subCount += (x - r);
                }

                System.out.println(Math.max(addCount , subCount));
            } 

            // 现在进一步进行判定

        }
    }
}
  • 忽然间想到,我是使用long保存的平均值,会报错,具体如下
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int T = in.nextInt();
        while (T-- > 0) { // 注意 while 处理多个 case
            int n = in.nextInt();
            int l = in.nextInt();
            int r = in.nextInt();
            int[] nums = new int[n];
            long sum = 0L;
            for(int i = 0;i < n;i ++)   {
                nums[i] = in.nextInt();
                sum += nums[i];
            }
            double avg = sum / (double)n;
            if(avg > r || avg < l)  System.out.println(-1);
            else{
                long subCount = 0;
                long addCount = 0;
                for(int x:nums){
                    if(x < l)   addCount += (l - x);
                    if(x > r)   subCount += (x - r);
                }

                System.out.println(Math.max(addCount , subCount));
            } 

            // 现在进一步进行判定

        }
    }
}

在这里插入图片描述

第五题

在这里插入图片描述
个人实现

  • 这个先简单点,直接用滑动窗口去做,然后统计一下每一次滑动窗口是否符合条件!但是问题在于,如何写出一个统计函数,计算每一个子串是不是好串!怎么写?需要记录一下状态,也就是每一个序列中,到当前序列而言,对应的零和一的数量,然后在进行计算!
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            String str = in.next();
            char chars[] = str.toCharArray();

            // 使用滑动窗口进行遍历
            int count0 = 0;
            int count1 = 0;
            int res = 0;
            int n = chars.length;
            for (int l = 0, r = 0; r < n; r++) {
                if (chars[r] == '0') count0 ++;
                if (chars[r] == '1') count1 ++;
                // 移动l,保证l到r是一个好子串
                while (l <= r && count0 < count1) {
                    if (chars[l] == '0') count0 --;
                    else count1 --;
                    l ++;
                }
                if (count0 > count1)
                    res ++;
            }
            System.out.println(res);
        }
    }
}

总结

  • 写的快,但是通过的样例也少了,如果按照正常的考试时间安排,能够通过三个题,差不多可以进面。第四题,应该还有其他的方法,这里直接看解析!

再次尝试,使用状态记录

  • 效果属实一般,全部超时!
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            String str = in.next();
            char chars[] = str.toCharArray();

            // 使用滑动窗口进行遍历
            int count0 = 0;
            int count1 = 0;
            int res = 0;
            int n = chars.length;
            int[][][] dp = new
            int[n][n][3];  // 第一个数字表示1合法序列,0未非法序列,后续两个分别是0和1的数量
            for (int l = 0; l < n; l++) {
                for (int r = l ; r < n; r ++) {
                    if (l == r) {
                        if (chars[l] == '0') {
                            dp[l][r][0] = 1;
                            dp[l][r][1] = 1;
                            dp[l][r][2] = 0;
                            res ++;
                        } else {
                            dp[l][r][0] = 0;
                            dp[l][r][1] = 0;
                            dp[l][r][2] = 1;
                        }
                    }
                    // 两者不相等,直接进行判断
                    else {
                        // 更新一下0和1的数量
                        if (chars[r] == '0') {
                            dp[l][r][1] = dp[l][r - 1][1] + 1;
                        } else {
                            dp[l][r][2] = dp[l][r - 1][2] + 1;
                        }

                        if (dp[l][r - 1][0] == 0) {
                            // 上一个状态的子串是非法的
                            dp[l][r][0] = 0;
                        } else {
                            if (dp[l][r][1] > dp[l][r][2]) {
                                // 0的数量大于1,那么直接更新
                                dp[l][r][0] = 1;
                                res ++;

                            } else {
                                dp[l][r][0] = 0;
                            }
                        }
                    }
                }
            }
            System.out.println(res);
        }
    }
}
参考实现
  import java.util.*; 
 
    
 
  class Main { 
 
      static final int MAXN = (int) (1e5 + 10); 
 
      static char[] chs = new char[MAXN]; 
 
      static long res = 0; 
 
      public static void main(String[] args) { 
 
    
 
          Scanner scanner = new Scanner(System.in); 
 
          String s = scanner.next(); 
 
          int n = s.length(); 
 
          for(int i = 1; i <= n; i++) { 
 
              chs[i] = s.charAt(i - 1); 
 
          } 
 
          int cnt1 = 0, cnt0 = 0; 
 
          for(int l = 1, r = 1; r <= n; r++) { 
 
              if(chs[r] == '0') 
 
                  cnt0++; 
 
              else 
 
                  cnt1++; 
 
    
 
              while(cnt1 >= cnt0 && l <= r) { 
 
                  if(chs[l] == '0') 
 
                      cnt0--; 
 
                  else 
 
                      cnt1--; 
 
                  l++; 
 
              } 
 
              res += (r - l + 1); 
 
              res -= 2L * cnt1; 
 
          } 
 
          System.out.println(res); 
 
      } 
 
  }

总结

  • 基本思路都是滑动窗口的,但是最后那里去除不合法子串那里,有点问题,感觉有点疑惑,然后计算所有合法子串那里确实世界计算r-l +1 的结果,因为开头变了,子串的状态就变了!

总结

  • 提前练了一下携程的笔试,感觉还行,基本上能过个三四题!继续加油!冲!

http://www.kler.cn/news/302647.html

相关文章:

  • 数据库的实施过程分析
  • 【白话树】之 树的基本知识、存储结构和二叉树转换
  • RabbitMQ创建交换机和队列——配置类 注解
  • Idea 创建 Maven项目的时候卡死
  • 体育数据API纳米足球数据API:足球数据接口文档API示例⑫
  • 【解决方案】双系统中修复ubuntu引导
  • 【算法】-单调队列
  • 数据库系统 第43节 数据库复制
  • LabVIEW回转马达试验系统
  • Git撤销add
  • Flutter类
  • Vue:通过js控制css变量 - 一键修改全局样式
  • Docker 常用命令(未完待续...)
  • 外贸网站建设该怎么做
  • Certbot 生成 SSL 证书并配置自动续期
  • android 发一个可以下载的的android studio历史版本
  • 深度学习——pycharm配置远程服务器(蓝耘GPU智算云)
  • JavaScript拷贝的艺术:玩转深拷贝和浅拷贝
  • Arcgis字段计算器:随机生成规定范围内的数字
  • vue2中使用web worker启动定时器
  • 25届计算机专业选题推荐-基于微信小程序的校园快递驿站代收管理系统
  • 修改docker的默认存储位置及镜像存储位置
  • 无人机低空安全管控系统技术详解
  • 2024年9月13日随笔
  • c++中extern “C“的作用及理解
  • 【FFMPEG】FFplay音视频同步分析(下)
  • 仕考网:2525年国考时间是什么时候?
  • Maven基本使用(下)
  • 无头服务(Headless Service)
  • 按图搜索的实时性:阿里巴巴拍立淘API返回值的快速响应