第 215 场力扣周赛题解

先附上本次周赛排名:

第 215 场力扣周赛题解_第1张图片

5601. 设计有序流

思路:利用map模拟题目过程即可。

class OrderedStream {

    int n, ptr;
    int[] arr;
    Map map;

    public OrderedStream(int n) {
        ptr = 1;
        this.n = n;
        arr = new int[n + 1];
        map = new HashMap<>();
    }

    public List insert(int id, String value) {
        List res = new ArrayList<>();
        if (id != ptr)
            map.put(id, value);
        else {
            int i = id;
            map.put(id, value);
            for (; i <= n; i++) {
                if (!map.containsKey(i))
                    break;
                res.add(map.get(i));
            }
            ptr = i;
        }
        return res;
    }
}

5603. 确定两个字符串是否接近

思路:记录下两个串中字符出现的数量,之后将这两个数组排序判断即可。

class Solution {
    public boolean closeStrings(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        if (n != m) return false;
        int[] a = new int[26];
        int[] b = new int[26];
        for (int i = 0; i < n; i++) {
            a[word1.charAt(i) - 'a']++;
            b[word2.charAt(i) - 'a']++;
        }
        for (int i = 0; i < 26; i++) {
            if (a[i] != 0 && b[i] == 0 || a[i] == 0 && b[i] != 0)
                return false;
        }
        Arrays.sort(a);
        Arrays.sort(b);
        for (int i = 0; i < 26; i++)
            if (a[i] != b[i])
                return false;
        return true;
    }
}

5602. 将 x 减到 0 的最小操作数

思路:这类题套路都一样,枚举左边拿了多少,利用后缀和优化右边能拿多少。

class Solution {
    public int minOperations(int[] nums, int x) {
        int n = nums.length;
        int[] sum = new int[n + 1];
        Map map = new HashMap<>();
        sum[n - 1] = nums[n - 1];
        int ans = n + 1;
        map.put(0, 0);
        for (int i = n - 1; i >= 0; i--) {
            sum[i] = sum[i + 1] + nums[i];
            if (sum[i] == x)
                ans = Math.min(ans, n - i);
            map.put(sum[i], n - i);
        }
        for (int i = 0; i < n; i++) {
            x -= nums[i];
            if (map.containsKey(x))
                ans = Math.min(ans, i + 1 + map.get(x));
        }
        return ans == n + 1 ? -1 : ans;
    }
}

5604. 最大化网格幸福感

思路:力扣好久没出这种质量较高的动态规划啦。

我们考虑状压dp。定义dp[i][j][k][x][y]:表示第i行外向的人放置的状态为j,内向的人放置的状态为k并且前i行已经使用了x个外向的人和y个内向的人的最大价值和。

class Solution {
    public int getMaxGridHappiness(int m, int n, int introvertsCount, int extrovertsCount) {
        int[][][][][] dp = new int[m][1 << n][1 << n][introvertsCount + 1][extrovertsCount + 1];
        for (int i = 0; i < m; i++)
            for (int j = 0; j < (1 << n); j++)
                for (int k = 0; k < (1 << n); k++)
                    for (int x = 0; x <= introvertsCount; x++)
                        for (int y = 0; y <= extrovertsCount; y++)
                            dp[i][j][k][x][y] = -1;
        for (int i = 0; i < (1 << n); i++)
            for (int j = 0; j < (1 << n); j++) {
                if (!check(i, j, introvertsCount, extrovertsCount))
                    continue;
                int num1 = findNum(i);
                int num2 = findNum(j);
                dp[0][i][j][num1][num2] = findSum(i, j);
            }
        for (int i = 1; i < m; i++)
            for (int x = 0; x < (1 << n); x++)
                for (int y = 0; y < (1 << n); y++) {
                    if (!check(x, y, introvertsCount, extrovertsCount))
                        continue;
                    int last1 = findNum(x);
                    int last2 = findNum(y);
                    for (int num1 = 0; num1 <= introvertsCount; num1++)
                        for (int num2 = 0; num2 <= extrovertsCount; num2++) {
                            if (last1 > num1 || last2 > num2 || dp[i - 1][x][y][num1][num2] == -1)
                                continue;
                            for (int xx = 0; xx < (1 << n); xx++)
                                for (int yy = 0; yy < (1 << n); yy++) {
                                    if (!check(xx, yy, introvertsCount - num1, extrovertsCount - num2))
                                        continue;
                                    int now1 = findNum(xx);
                                    int now2 = findNum(yy);
                                    int sum = dp[i - 1][x][y][num1][num2];
                                    int state = x & xx;
                                    sum -= findNum(state) * 30 * 2;
                                    state = x & yy;
                                    sum = sum - findNum(state) * 30 + findNum(state) * 20;
                                    state = y & xx;
                                    sum = sum + findNum(state) * 20 - findNum(state) * 30;
                                    state = y & yy;
                                    sum += findNum(state) * 20 * 2;
                                    dp[i][xx][yy][num1 + now1][num2 + now2] =
                                            Math.max(dp[i][xx][yy][num1 + now1][num2 + now2], sum + findSum(xx, yy));
                                }
                        }
                }
        int ans = 0;
        for (int i = 0; i < (1 << n); i++)
            for (int j = 0; j < (1 << n); j++)
                for (int x = 0; x <= introvertsCount; x++)
                    for (int y = 0; y <= extrovertsCount; y++)
                        ans = Math.max(ans, dp[m - 1][i][j][x][y]);
        return ans;
    }

    private int findSum(int x, int y) {
        int z = x | y;
        int ans = findNum(x) * 120 + findNum(y) * 40;
        ans -= findNum(x & (z << 1)) * 30;
        ans -= findNum(x & (z >> 1)) * 30;
        ans += findNum(y & (z << 1)) * 20;
        ans += findNum(y & (z >> 1)) * 20;
        return ans;
    }

    private int findNum(int x) {
        int num = 0;
        while (x > 0) {
            if ((x & 1) != 0)
                num++;
            x >>= 1;
        }
        return num;
    }

    private boolean check(int x, int y, int xx, int yy) {
        if ((x & y) != 0) return false;
        return findNum(x) <= xx && findNum(y) <= yy;
    }
}

 

你可能感兴趣的:(第 215 场力扣周赛题解)