G
N
I
D
A
O
L

力扣第 340 场周赛

题目链接:https://leetcode.cn/contest/weekly-contest-340/

# T1. 对角线上的质数

链接:https://leetcode.cn/problems/prime-in-diagonal/

# 代码

a
class Solution {
    public int diagonalPrime(int[][] nums) {
        int n = nums.length;
        int max = 0;
        for (int i = 0; i < n; ++i) {
            if (max < nums[i][i] && isPrime(nums[i][i])) {
                max = nums[i][i];
            }
            if (max < nums[i][n - 1 - i] && isPrime(nums[i][n - 1 - i])) {
                max = nums[i][n - 1 - i];
            }
        }
        
        return max;
    }
    private boolean isPrime(int k) {
        if (k < 2) return false;
        int q = (int) Math.sqrt(k);
        for (int i = 2; i <= q; ++i) {
            if (k % i == 0) return false;
        }
        return true;
    }
}

# T2. 等值距离和

链接:https://leetcode.cn/problems/sum-of-distances/

# 解题思路:HashMap + 累加前缀和

  • 将数组中的相同值的下标分成一组
  • 计算每一组内的各个下标的距离之和,这个可以使用递推进行计算,减少时间复杂度:
    • dp[i] = dp[i-1] + (i-1) * (arr[i] - arr[i-1])dp[i] 表示 0, 1, ... i-1 到 i 的距离之和

# 提交结果

image.png

# 代码

class Solution {
    public long[] distance(int[] nums) {
        int n = nums.length;
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < n; ++i) {
            List<Integer> list = map.get(nums[i]);
            if (list == null) {
                list = new ArrayList<>();
                list.add(i);
                map.put(nums[i], list);
            } else {
                list.add(i);
            }
        }
        long[] arr = new long[n];
        for (Map.Entry<Integer, List<Integer>> e : map.entrySet()) {
            List<Integer> vals = e.getValue();
            if (vals != null && vals.size() > 1) {
                int sz = vals.size();
                long[] dp = new long[sz];
                for (int i = sz - 2; i >= 0; --i) {
                    dp[i] = dp[i + 1] + (long) (sz - 1 - i) * (vals.get(i + 1) - vals.get(i));
                }
                long preSum = 0;
                for (int i = 0; i < sz; ++i) {
                    if (i > 0) {
                        preSum += (long) i * (vals.get(i) - vals.get(i - 1));
                    }
                    arr[vals.get(i)] = preSum + dp[i];
                }
            }
        }
        return arr;
    }
}

# T3. 最小化数对的最大差值

链接:

# 思路:二分枚举

具体见代码注释

# 代码

a
class Solution {
    public int minimizeMax(int[] nums, int p) {
        int n = nums.length;
        if (n < 2 || p < 1) return 0;
        Arrays.sort(nums);
        int left = 0, right = nums[n - 1] - nums[0];
        // 标记数组
        boolean[] vis = new boolean[n];
        // 二分搜索每一个值
        while (left < right) {
            int mid = left + (right - left) / 2;
            Arrays.fill(vis, false);
            int pair = 0;
            
            for (int i = 1, j = 0; pair < p && i < n; ++i) {
                while (j < i && (nums[i] - nums[j] > mid || vis[j])) ++j;
                if (j < i) {
                    // 找到一对 <= mid 差值对
                    vis[i] = true;
                    vis[j] = true;
                    ++pair;
                }
            }
            
            // 当前枚举的 mid 已经找到了 p 对差值对,可能还会有更小的
            if (pair == p) right = mid;
            // 没有找到 <= mid 的 p 对差值对,需要扩大查找范围
            else left = mid + 1;
        }
        return left;
    }
}

# T4. 网格图中最少访问的格子数

题目链接:https://leetcode.cn/problems/minimum-number-of-visited-cells-in-a-grid/

# 解题思路

BFS 应用,需要使用 dis 来标记已经到达过的点

# 提交结果

image.png

# 代码

class Solution {
    public int minimumVisitedCells(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        // 处理特殊情况
        if (m < 2 && n < 2) return 1;
        Queue<int[]> que = new ArrayDeque<>();
        // 记录步数
        int[][] dis = new int[m][n];
        
        que.offer(new int[] {0, 0});
        dis[0][0] = 1;
        
        while (!que.isEmpty()) {
            for (int i = que.size(); i > 0; --i) {
                int[] d = que.poll();
                int cx = d[0];
                int cy = d[1];
                
                for (int x = cx + 1; x < m && x <= cx + grid[cx][cy]; ++x) {
                    if (dis[x][cy] == 0) {
                        // 没访问过
                        que.offer(new int[] {x, cy});
                        dis[x][cy] = dis[cx][cy] + 1;
                        // 到达目标点
                        if (x == m - 1 && cy == n - 1) return dis[x][cy];
                    }
                }
                for (int y = cy + 1; y < n && y <= cy + grid[cx][cy]; ++y) {
                    if (dis[cx][y] == 0) {
                        // 没访问过
                        que.offer(new int[] {cx, y});
                        dis[cx][y] = dis[cx][cy] + 1;
                        // 到达目标点
                        if (cx == m - 1 && y == n - 1) return dis[cx][y];
                    }
                }
            }
        }
        
        return -1;
    }
}
更新于 阅读次数

😉觉得写的还不错,请我喝杯咖啡吧😁

独步凌波 微信支付

微信支付

独步凌波 支付宝

支付宝