美团 8.12 后端&数开&软件 笔试

只做出了三道半,最后一道参考这个大佬的思路https://www.nowcoder.com/discuss/519845427500285952

第一题:小美的排列询问

直接用map

 public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 1; i <= n; i++) {
            int t = sc.nextInt();
            map.put(t, i);
        }
        int x = sc.nextInt();
        int y = sc.nextInt();
        if(Math.abs(map.get(x)-map.get(y))==1){
            System.out.println("Yes");
        }else {
            System.out.println("No");
        }
    }

第二题:小美走公路

前缀和,注意数据范围,开long

最开始,用了两个for循环一个做输入,一个生成前缀和,结果只过了一半数据,猜测可能超时。后面优化只用一个循环同时完成输入和前缀和生成。

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long[] sum = new long[n+1];
        //前缀和
        for(int i = 1; i <= n; i++) {
            sum[i] = sc.nextLong();
            sum[i] += sum[i-1];
        }
        int x = sc.nextInt();
        int y = sc.nextInt();
        //取绝对值
        long res1 = Math.abs(sum[y-1]-sum[x-1]);
        long res2 = sum[n] -res1;
        long res = Math.min(res1,res2);
        System.out.println(res);
    }

第三题:小美的蛋糕切割

最开始这道题想复杂了,以为要二分,后来发现可以用二维前缀和解决,注意数据范围,要开long

定义:p[i][j] 记录 a 中子矩阵 [0, 0, i-1, j-1] 的元素和

    static int[][] a; 
    static long[][] p;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        a = new int[n][m];
        p = new long[n + 1][m + 1];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                a[i][j] = sc.nextInt();
            }
        }
        // 构造二维前缀和  m行 n列
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                p[i][j] = p[i - 1][j] + p[i][j - 1] - p[i - 1][j - 1] + a[i - 1][j - 1];
            }
        }
        long res = Integer.MAX_VALUE;
        for(int i= 1;i <= n;i++){  //横切 0,0 i,m
            res=  Math.min(res,Math.abs(p[i][m]- (p[n][m]-p[i][m])));
        }
        for(int j= 1;j <= m;j++){  //竖切 0,0, n,j
            res=  Math.min(res,Math.abs(p[n][j]- (p[n][m]-p[n][j])));
        }
        System.out.println(res);
    }

第四题:小美将字符串平铺成矩阵

暴力穷举因数,然后DFS搜索联通区域

static int n, m, k;
    //二维映射到一维 :n*m 二维坐标为(i,j)则一维坐标为i*m+j
    static char[] s;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};
    //DFS搜索
    public static void dfs(int x, int y, boolean[][] st) {
        int t = x * m + y;
        st[x][y] = true;
        for (int i = 0; i < 4; i++) {
            int a = x + dx[i];
            int b = y + dy[i];
            int z = a * m + b;
            if (a < 0 || a >= n || b < 0 || b >= m || st[a][b] || s[z] != s[t]){
                continue;
            }
            dfs(a, b, st);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        k = sc.nextInt();
        s = sc.next().toCharArray();
        int res = k;
        for (int i = 1; i <= k; i++) {
            if (k % i != 0) {  // 必须要可以整除
                continue;
            }
            n = i;
            m = k / i;
            boolean[][] st = new boolean[n][m];
            int cnt = 0;
            for (int j = 0; j < n; j++) {
                for (int l = 0; l < m; l++) {
                    if (!st[j][l]) {
                        cnt++;
                        dfs(j, l, st);
                    }
                }
            }
            res = Math.min(res, cnt);
        }
        System.out.println(res);
    }

第五题:小美将字符串平铺成矩阵

树形DP,太难想了,参考这个大佬的思路https://www.nowcoder.com/discuss/519845427500285952

每个节点可以染色或者不染色。设dp[u][1]表示将u节点染色 dp[u][0]表示不将u节点染色 染色的话,则必须只选择一个可以染色的孩子。dp[u][1]=dp[u][0]-max(dp[v][0],dp[v][1])+dp[v][0]+2 不染色的话,则孩子染色和不染色都可以,取最大值即可。dp[u][0]+=max(dp[v][1],dp[v][0])

    static int n, ans;
    static long[] a;
    static int[][] dp;
    static List<Integer>[] e;
    // 判断两数乘积是不是 完全平方数
    public static boolean x2(long x, long y) {
        long d = (long) Math.sqrt(x * y);
        return d * d == x * y;
    }
    public static void dfs(int u, int fa) {
        for (int v : e[u]) {
            if (v == fa) {
                continue;
            }
            dfs(v, u);
            dp[u][0] += Math.max(dp[v][1], dp[v][0]);
        }
        for (int v : e[u]) {
            if (v == fa || !x2(a[u], a[v])) {
                continue;
            }
            dp[u][1] = Math.max(dp[u][1], dp[u][0] - Math.max(dp[v][0], dp[v][1]) + 2 + dp[v][0]);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        a = new long[n + 1];
        for (int i = 1; i <= n; i++){
            a[i] = sc.nextLong();
        }
        e = new List[n + 1];
        for (int i = 1; i <= n; i++){
            e[i] = new ArrayList<>();
        }
        //邻接矩阵 构造树
        for (int i = 1; i < n; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();
            e[u].add(v);
            e[v].add(u);
        }

        dp = new int[n + 1][2];
        dfs(1, 0);
        ans = Math.max(dp[1][0], dp[1][1]);
        System.out.println(ans);
    }
#美团信息集散地#
全部评论
牛的
点赞
送花
回复
分享
发布于 2023-08-19 11:15 江西

相关推荐

9 25 评论
分享
牛客网
牛客企业服务