欢迎大家加QQ群:623375442,可以方便群里面交流。

100410. Check if Two Chessboard Squares Have the Same Color

给你两个字符串 coordinate1 和 coordinate2,代表 8 x 8 国际象棋棋盘上的两个方格的坐标。

测试样例:

输入:coordinate1 = "a1", coordinate2 = "c3"

输出:true

解释:两个方格均为黑色。

解答:暴力枚举一下两个位置的颜色。

class Solution {
    public boolean checkTwoChessboards(String coordinate1, String coordinate2) {
        if (coordinate1.equals(coordinate2)) {
            return true;
        }
        int c1 = -1, c2 = -1;
        for (char l = 'a'; l <= 'h'; ++l) {
            int c = (l - 'a') % 2;
            for (int n = 1; n <= 8; ++n) {
                if (coordinate1.charAt(0) == l && coordinate1.charAt(1) - '0' == n) {
                    c1 = c;
                } else if (coordinate2.charAt(0) == l && coordinate2.charAt(1) - '0' == n) {
                    c2 = c;
                }
                c ^= 1;
            }
        }
        return c1 == c2;
    }
}

100412. Final Array State After K Multiplication Operations II

有一个无限大的二维平面。

给你一个正整数 k ,同时给你一个二维数组 queries ,包含一系列查询:

  • queries[i] = [x, y] :在平面上坐标 (x, y) 处建一个障碍物,数据保证之前的查询 不会 在这个坐标处建立任何障碍物。

每次查询后,你需要找到离原点第 k 近 障碍物到原点的 距离 。

请你返回一个整数数组 results ,其中 results[i] 表示建立第 i 个障碍物以后,离原地第 k 近障碍物距离原点的距离。如果少于 k 个障碍物,results[i] == -1 。

注意,一开始 没有 任何障碍物。

坐标在 (x, y) 处的点距离原点的距离定义为 |x| + |y| 。

测试样例:

输入:queries = [[1,2],[3,4],[2,3],[-3,0]], k = 2

输出:[-1,7,5,3]

解释:最初,不存在障碍物。

  • queries[0] 之后,少于 2 个障碍物。
  • queries[1] 之后, 两个障碍物距离原点的距离分别为 3 和 7 。
  • queries[2] 之后,障碍物距离原点的距离分别为 3 ,5 和 7 。
  • queries[3] 之后,障碍物距离原点的距离分别为 3,3,5 和 7 。

解答:典型的优先队列题目,记录最小的k个数字。

class Solution {
    public int[] resultsArray(int[][] queries, int k) {
        int[] res = new int[queries.length];
        PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> (Integer.compare(b, a)));
        for (int i = 0; i < queries.length; ++i) {
            queue.add(Math.abs(queries[i][0]) + Math.abs(queries[i][1]));
            if (queue.size() > k) {
                queue.poll();
            }
            if (queue.size() == k) {
                res[i] = queue.peek();
            } else {
                res[i] = -1;
            }
        }
        return res;
    }
}

100419. Select Cells in Grid With Maximum Score

给你一个由正整数构成的二维矩阵 grid。

你需要从矩阵中选择 一个或多个 单元格,选中的单元格应满足以下条件:

  • 所选单元格中的任意两个单元格都不会处于矩阵的 同一行。
  • 所选单元格的值 互不相同。

你的得分为所选单元格值的总和。

返回你能获得的 最大 得分。

测试样例:

输入:grid = [[1,2,3],[4,3,2],[1,1,1]]

输出:8

解释:对应的值分别为 1、3 和 4 。

解答:这题范围太小了。直接用一点动态规划开始暴力。我们先记录每个数字出现的行数情况。然后暴力枚举买一种行取的情况下,最大值。

class Solution {
    public int maxScore(List<List<Integer>> grid) {
        int m = grid.size();
        Set<Integer>[] map = new Set[101];
        for (int i = 0; i <= 100; ++i) {
            map[i] = new HashSet<>();
        }
        for (int i = 0; i < grid.size(); ++i) {
            List<Integer> row = grid.get(i);
            for (int n : row) {
                map[n].add(i);
            }
        }

        // 动态规划,记录每一种行取的情况下,最大值。
        int[] dp = new int[1 << m];
        Arrays.fill(dp, -1);
        // 0代表一行都不取,这个时候是0
        dp[0] = 0;
        int res = 0;
        for (int i = 100; i >= 1; --i) {
            if (!map[i].isEmpty()) {
                // 暴力枚举一下每种数字下,每种行取的情况下,最大值。
                int[] nextDP = new int[1 << m];
                for (int j = 0; j < (1 << m); ++j) {
                    nextDP[j] = dp[j];
                }

                for (int n : map[i]) {
                    for (int j = 0; j < dp.length; ++j) {
                        if (dp[j] == -1) continue;
                        int mark = (j >> n) & 1;
                        if (mark == 0) {
                            int tmp = j + (1 << n);
                            nextDP[tmp] = Math.max(nextDP[tmp], dp[j] + i);
                            res = Math.max(res, nextDP[tmp]);
                        }
                    }
                }
                dp = nextDP;
            }
        }
        return res;
    }
}

100408. Maximum XOR Score Subarray Queries

给你一个由 n 个整数组成的数组 nums,以及一个大小为 q 的二维整数数组 queries,其中 queries[i] = [li, ri]。

对于每一个查询,你需要找出 nums[li..ri] 中任意 子数组 的 最大异或值。

数组的异或值 需要对数组 a 反复执行以下操作,直到只剩一个元素,剩下的那个元素就是 异或值:

  • 对于除最后一个下标以外的所有下标 i,同时将 a[i] 替换为 a[i] XOR a[i + 1] 。
  • 移除数组的最后一个元素。

返回一个大小为 q 的数组 answer,其中 answer[i] 表示查询 i 的答案。

测试样例:

输入:nums = [2,8,4,32,16,1], queries = [[0,2],[1,4],[0,5]]

输出:[12,60,60]

解释:在第一个查询中,nums[0..2] 的子数组分别是 [2], [8], [4], [2, 8], [8, 4], 和 [2, 8, 4],它们的异或值分别为 2, 8, 4, 10, 12, 和 6。查询的答案是 12,所有异或值中的最大值。

在第二个查询中,nums[1..4] 的子数组中最大的异或值是子数组 nums[1..4] 的异或值,为 60。

在第三个查询中,nums[0..5] 的子数组中最大的异或值是子数组 nums[1..4] 的异或值,为 60。

解答:这题脑筋急转弯。用几个例子试验一下,就能知道x到y的数组异或值XOR[x][y] = XOR[x - 1][y] ^ XOR[x][y - 1]。之后就退化成区间最大值了。

class Solution {
    public int[] maximumSubarrayXor(int[] nums, int[][] queries) {
        int len = nums.length;
        int[][] dp = new int[len][len];
        for (int i = 0; i < len; ++i) {
            int st = 0, ed = i;
            // 按照公式计算数组异或值
            while (ed < len) {
                if (i == 0) {
                    dp[st][ed] = nums[st];
                } else {
                    dp[st][ed] = dp[st][ed - 1] ^ dp[st + 1][ed];
                }
                ++st;
                ++ed;
            }
        }

        // 求区间最大值
        int[][] rangeMax = new int[len][len];
        for (int i = 0; i < len; ++i) {
            int st = 0, ed = i;
            while (ed < len) {
                if (i == 0) {
                    rangeMax[st][ed] = dp[st][ed];
                } else {
                    rangeMax[st][ed] = Math.max(dp[st][ed], Math.max(rangeMax[st][ed - 1], rangeMax[st + 1][ed]));
                }
                ++st;
                ++ed;
            }

        }

        int[] res = new int[queries.length];
        for (int i = 0; i < res.length; ++i) {
            res[i] = rangeMax[queries[i][0]][queries[i][1]];
        }
        return res;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *