8月19日:美团笔试第3 4 5题

第3题:01子串,二维 dp

三维 dp:dp[i][j][0] 表示 s.charAt(j) 变为 0 的操作次数,dp[i][j][1] 表示 s.charAt(j) 变为 1 的操作次数。画个图就知道了。

遍历 ij 时,j 的变换不依赖 i,因此存储可以优化为二维 dp[n][2]。

因为要遍历每个子串,因此,res += Math.min(dp[j][0], dp[j][1])

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String s = cin.next();
        int n = s.length();
        int[][] dp = new int[n][2]; // 优化前:dp[n][n][2]
        int res = 0;

        for (int i = 0; i < n - 1; i++) {
            for (int j = i; j < n; j++) {
                if (i == j) {
                    dp[j][0] = s.charAt(i) == '0' ? 0 : 1;
                    dp[j][1] = s.charAt(i) == '1' ? 0 : 1;
                } else {
                    dp[j][0] = s.charAt(j) == '0' ? dp[j - 1][1] : dp[j - 1][1] + 1;
                    dp[j][1] = s.charAt(j) == '1' ? dp[j - 1][0] : dp[j - 1][0] + 1;
                    res += Math.min(dp[j][0], dp[j][1]);
                }
            }
        }
        System.out.println(res);
    }
}

第4题:和相等的数组个数,二维 dp

回溯超时,但是可以作为验证,因此两种方案都给出。

二维 dp

dp[i][j]:下标为 [0, i] 的子数组 sub 中和为 j 的个数,k 表示子数组 sub 的下标 i 的值,依次遍历,注意剔除 nums[i] == k。

例如:nums = [1, 2, 4]。dp[1][5] = 表示下标为 [0, 1] 的子数组中和为 5 的个数,包括 [2, 3], [4, 1]。[1, 4] 和 [3, 2] 都不满足要求

注意,i == n - 1 时,只需计算最后一个值 dp[n - 1][sum],即是最终答案。

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] nums = new int[n];
        int sum = 0;
        for (int i = 0; i < n; i++) {
            nums[i] = cin.nextInt();
            sum += nums[i];
        }

        int MOD = (int) 1e9 + 7;
        long[][] dp = new long[n][sum + 1];
        for (int i = 0; i < n; i++) {
            for (int j = 1; j < sum; j++) {
                if (i == 0) {
                    if (nums[i] != j) {
                        dp[i][j] = 1;
                    }
                    continue;
                }
                if (i == n - 1) {
                    j = sum;
                }
                for (int k = 1; k <= j; k++) {
                    if (nums[i] == k) {
                        continue;
                    }
                    dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % MOD;
                }
            }
        }
        // 打印 dp
//        for (int j = 1; j <= sum; j++) {
//            System.out.print(j + " ");
//        }
//        System.out.println();
//        for (int i = 0; i < n; i++) {
//            for (int j = 1; j <= sum; j++) {
//                System.out.print(dp[i][j] + " ");
//            }
//            System.out.println();
//        }
        System.out.println(dp[n - 1][sum]);
    }
}

回溯(超时,可打印具体数组验证)

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Solution {

    public static int MOD = (int) 1e9 + 7;
    public static int res = 0;
    public static List<List<Integer>> ans = new ArrayList<>();

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] nums = new int[n];
        int sum = 0;
        for (int i = 0; i < n; i++) {
            nums[i] = cin.nextInt();
            sum += nums[i];
        }
        backtrack(new ArrayList<>(), nums, 0, sum, nums.length);
        System.out.println(ans);
        System.out.println(res);
    }

    public static void backtrack(List<Integer> list, int[] nums, int i, int rest, int n) {
        if (i == n || rest == 0) {
            if (i == n && rest == 0) {
                res = (res + 1) % MOD;
                ans.add(new ArrayList<>(list));
            }
            return;
        }

        for (int num = 1; num <= rest; num++) {
            if (num == nums[i]) {
                continue;
            }
            list.add(num);
            backtrack(list, nums, i + 1, rest - num, n);
            list.remove(list.size() - 1);
        }
    }
}

第5题:讲真,有点东西

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static int n;
    public static int[] nums;
    public static long sum;

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        n = cin.nextInt();
        nums = new int[n];
        sum = 0;
        for (int i = 0; i < n; i++) {
            nums[i] = cin.nextInt();
            sum += nums[i];
        }
        Arrays.sort(nums);

        long avg = sum / n;
        if (avg * n == sum) {
            long res = 0;
            for (int num : nums) {
                res += Math.abs(num - avg);
            }
            System.out.println(res >> 1);
        } else {
            System.out.println(Math.min(
                    Math.min(cal(true, true, sum - nums[n - 1]), cal(true, false, sum - nums[n - 1])),
                    Math.min(cal(false, true, sum - nums[0]), cal(false, false, sum - nums[0]))
            ));
        }
    }

    public static long cal(boolean isLeft, boolean isFloor, long sum) {
        double a = 1.0 * sum / (n - 1);
        long avg = (long) (isFloor ? Math.floor(a) : Math.ceil(a));
        long diff = Math.abs(sum - avg * (n - 1));
        long res = 0;

        if (isLeft) {
            nums[n - 2] -= isFloor ? diff : 0;
            nums[0] += isFloor ? 0 : diff;
            for (int i = 0; i < n - 1; i++) {
                res += Math.abs(nums[i] - avg);
            }
            nums[n - 2] += isFloor ? diff : 0;
            nums[0] -= isFloor ? 0 : diff;
        } else {
            nums[n - 1] -= isFloor ? diff : 0;
            nums[1] += isFloor ? 0 : diff;
            for (int i = 1; i < n; i++) {
                res += Math.abs(nums[i] - avg);
            }
            nums[n - 1] += isFloor ? diff : 0;
            nums[1] -= isFloor ? 0 : diff;
        }
        return diff + res / 2;
    }
}

#美团笔试##美团信息集散地#
全部评论

相关推荐

05-22 12:44
已编辑
门头沟学院 golang
点赞 评论 收藏
分享
评论
点赞
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务