力扣第 340 场周赛
题目链接:https://leetcode.cn/contest/weekly-contest-340/
# T1. 对角线上的质数
链接:https://leetcode.cn/problems/prime-in-diagonal/
# 代码
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 的距离之和
# 提交结果
# 代码
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. 最小化数对的最大差值
链接:
# 思路:二分枚举
具体见代码注释
# 代码
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 来标记已经到达过的点
# 提交结果
# 代码
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; | |
} | |
} |