力扣第 341 场周赛题解
题目链接:https://leetcode.cn/contest/weekly-contest-341/
# T1. 一最多的行
链接:https://leetcode.cn/problems/row-with-maximum-ones/
# 思路
模拟
# 代码
class Solution { | |
public int[] rowAndMaximumOnes(int[][] mat) { | |
int row = -1; | |
int cnt = -1; | |
for (int i = 0; i < mat.length; ++i) { | |
int c = 0; | |
for (int j = 0; j < mat[i].length; ++j) { | |
if (mat[i][j] == 1) ++c; | |
} | |
if (c > cnt) { | |
cnt = c; | |
row = i; | |
} | |
} | |
return new int[] {row, cnt}; | |
} | |
} |
# T2. 找出可整除性得分最大的整数
链接:https://leetcode.cn/problems/find-the-maximum-divisibility-score/
# 思路
按题目模拟即可
# 代码
class Solution { | |
public int maxDivScore(int[] nums, int[] divisors) { | |
int n = nums.length; | |
int score = -1; | |
int ret = Integer.MAX_VALUE; | |
for (int d : divisors) { | |
int s = 0; | |
for (int i = 0; i < n; ++i) { | |
if (nums[i] % d == 0) { | |
++s; | |
} | |
} | |
if (s > score) { | |
score = s; | |
ret = d; | |
} else if (s == score) { | |
ret = Math.min(ret, d); | |
} | |
} | |
return ret; | |
} | |
} |
# T3. 构造有效字符串的最少插入数
链接:https://leetcode.cn/problems/minimum-additions-to-make-valid-string/
# 法一:利用周期性
最后字符串要变成: abcabcabc...
呈周期循环
如果当前的字符比它前一个字符大,说明:当前字符和前一个字符构成一个周期;
否则当前字符形成一个新周期
最后的插入字符数为 3 * T - len(s)
,T 为周期数
# 代码
class Solution { | |
public int addMinimum(String word) { | |
char[] chs = word.toCharArray(); | |
int n = chs.length; | |
// 至少一个周期 | |
int t = 1; | |
for (int i = 1; i < n; ++i) { | |
if (chs[i] <= chs[i - 1]) ++t; | |
} | |
return 3 * t - n; | |
} | |
} |
- 模拟
- if-else 枚举,适用于字符串较短
- 数学法进行优化:
# 代码
if-else 穷举:
class Solution { | |
public int addMinimum(String word) { | |
int cnt = 0; | |
char[] chs = word.toCharArray(); | |
int n = chs.length; | |
for (int i = 0; i < n; ++i) { | |
if (chs[i] == 'a') { | |
if (i + 1 < n && chs[i + 1] == 'b') { | |
++i; | |
if (i + 1 < n && chs[i + 1] == 'c') { | |
++i; | |
} else { | |
++cnt; | |
} | |
} else if (i+1 < n && chs[i+1] == 'c'){ | |
++i; | |
++cnt; | |
} else { | |
cnt += 2; | |
} | |
} else if (chs[i] == 'b'){ | |
++cnt; | |
if (i + 1 < n && chs[i+1] == 'c') { | |
++i; | |
} else { | |
++cnt; | |
} | |
} else { | |
cnt+= 2; | |
} | |
} | |
return cnt; | |
} | |
} |
利用数学方法优化:
class Solution { | |
public int addMinimum(String word) { | |
char[] chs = word.toCharArray(); | |
int n = chs.length; | |
/** | |
* 将字符串分成 【中间插入】 和 【首尾插入】,即 aaa -> _a_a_a_, '_' 表示待插入字符串的位置 | |
* | |
* 处理第一字符:chs [0] - 'a' | |
* 处理末尾字符:'c' - chs [n-1] | |
* | |
* 中间位置 | |
* aa -> abca -> 2 | |
* ab -> ab -> 0 | |
* ac -> abc -> 1 | |
* cb -> cab -> 1 | |
* ...... | |
* | |
* 即: | |
* (chs [i] - chs [i-1] - 1 + 3) % 3 | |
*/ | |
int cnt = chs[0] - chs[n-1] + 2; | |
// 处理中间插入位置 | |
for (int i = 1; i < n; ++i) { | |
cnt += (chs[i] - chs[i - 1] + 2) % 3; | |
} | |
return cnt; | |
} | |
} |
# T4. 最小化旅行的价格总和
链接:https://leetcode.cn/problems/minimize-the-total-price-of-the-trips/
# 思路
待补充
# 代码
class Solution { | |
private List<Integer>[] g; | |
private int[] price, cnt; | |
private int end; | |
public int minimumTotalPrice(int n, int[][] edges, int[] price, int[][] trips) { | |
g = new ArrayList[n]; | |
Arrays.setAll(g, e -> new ArrayList<>()); | |
for (var e : edges) { | |
int x = e[0], y = e[1]; | |
g[x].add(y); | |
g[y].add(x); // 建树 | |
} | |
this.price = price; | |
cnt = new int[n]; | |
for (var t : trips) { | |
end = t[1]; | |
path(t[0], -1); | |
} | |
var p = dfs(0, -1); | |
return Math.min(p[0], p[1]); | |
} | |
private boolean path(int x, int fa) { | |
if (x == end) { // 到达终点(注意树只有唯一的一条简单路径) | |
++cnt[x]; // 统计从 start 到 end 的路径上的点经过了多少次 | |
return true; // 找到终点 | |
} | |
for (var y : g[x]) | |
if (y != fa && path(y, x)) { | |
++cnt[x]; // 统计从 start 到 end 的路径上的点经过了多少次 | |
return true; // 找到终点 | |
} | |
return false; // 未找到终点 | |
} | |
// 类似 337. 打家劫舍 III https://leetcode.cn/problems/house-robber-iii/ | |
private int[] dfs(int x, int fa) { | |
int notHalve = price[x] * cnt[x]; //x 不变 | |
int halve = notHalve / 2; //x 减半 | |
for (var y : g[x]) | |
if (y != fa) { | |
var p = dfs(y, x); // 计算 y 不变 / 减半的最小价值总和 | |
notHalve += Math.min(p[0], p[1]); //x 不变,那么 y 可以不变,可以减半,取这两种情况的最小值 | |
halve += p[0]; //x 减半,那么 y 只能不变 | |
} | |
return new int[]{notHalve, halve}; | |
} | |
} |