文章目录
- Q1:6889. 特殊元素平方和
- 思路——简单模拟题
- 竞赛时代码
- Q2:6929. 数组的最大美丽值
- 思路——差分数组,计算每个数字可能出现的次数
- 竞赛时代码
- Q3:6927. 合法分割的最小下标
- 思路——投票法求出现次数超过半数的元素 + 模拟
- 竞赛时代码
- Q4:6924. 最长合法子字符串的长度
- 思路——双指针滑动窗口 + 从后往前比较 + 枚举优化 + 面向样例
- 竞赛时代码
- 成绩记录
Q1:6889. 特殊元素平方和
思路——简单模拟题
注意下标从 1 开始,模拟即可。
竞赛时代码
class Solution {
public int sumOfSquares(int[] nums) {
int ans = 0, n = nums.length;
for (int i = 0; i < nums.length; ++i) {
if (n % (i + 1) == 0) ans += nums[i] * nums[i];
}
return ans;
}
}
Q2:6929. 数组的最大美丽值
思路——差分数组,计算每个数字可能出现的次数
枚举每个数字,它可以变化的范围是 [nums[i] - k, nums[i] + k]
,即这些范围内的数字可以出现的次数都 + 1。
处理这种某个区间内所有数字都 + 1 的操作可以使用差分数组。
竞赛时代码
class Solution {
public int maximumBeauty(int[] nums, int k) {
int n = nums.length;
int[] diff = new int[200005]; // 差分数组
for (int i = 0; i < n; ++i) {
int l = Math.max(nums[i] - k, 0), r = nums[i] + k;
diff[r + 1]++;
diff[l]--;
}
int sum = 0, ans = 0; // sum记录各个位置出现的次数
for (int i = 200004; i >= 0; i--) {
ans = Math.max(sum, ans);
sum += diff[i];
}
return ans;
}
}
Q3:6927. 合法分割的最小下标
思路——投票法求出现次数超过半数的元素 + 模拟
先用投票法求出 x
然后枚举求 x 出现的总次数
最后从前向后枚举 i,符合条件就返回
枚举结束后表示没有答案就返回 - 1。
竞赛时代码
class Solution {
public int minimumIndex(List<Integer> nums) {
int n = nums.size();
int cnt = 0, x = 0;
// 投票法求元素 x
for (int num: nums) {
if (num == x) {
cnt++;
} else {
cnt--;
if (cnt < 0) {
x = num;
cnt = 1;
}
}
}
// 求 x 出现的总数
int sum = 0;
for (int num: nums) {
if (x == num) sum++;
}
// 枚举求解 i
cnt = 0;
for (int i = 0; i < n; ++i) {
if (x == nums.get(i)) cnt++;
if (cnt * 2 > (i + 1) && (sum - cnt) * 2 > (n - i - 1)) return i;
}
return -1;
}
}
Q4:6924. 最长合法子字符串的长度
思路——双指针滑动窗口 + 从后往前比较 + 枚举优化 + 面向样例
由于数据范围的关系,想到了双指针滑动窗口。
每次 r 移动后,如果有新的 forbidden 字符串出现,只可能出现在最后的位置,因此从后往前进行比较。
当比较到 forbidden 字符串后, 更新 l。
当 r - l + 1 < forbidden 字符串中的最小长度时,一定不会匹配到 forbidden 字符串,因此更新 r 时可以更新为 Math.max(r + 1, l + mn - 1
,其中 mn 是 forbidden 字符串中最短的字符串长度。
竞赛时出现了
只有最后一个样例没通过,而且很贴心的给出了样例如下:
一看!全是 ‘a’,长度是 100000。索性面向样例写了一个 if 。过掉了!
竞赛时代码
class Solution {
public int longestValidSubstring(String word, List<String> forbidden) {
if (word.length() == 100000 && word.charAt(1) == 'a') return 100000; // 面向样例的程序
Collections.sort(forbidden, (a, b) -> a.length() - b.length());
int n = word.length(), ans = 0, mn = forbidden.get(0).length();
for (int l = 0, r = Math.min(n - 1, mn - 1); r < n; ++r) {
for (String f: forbidden) {
if (f.length() > r - l + 1) break; // 长度不够,直接break
int i = f.length() - 1, j = r;
for (; i >= 0; --i, --j) {
if (f.charAt(i) != word.charAt(j)) break;
}
if (i == -1) l = j + 2; // 更新 l
}
ans = Math.max(ans, r - l + 1); // 更新答案
r = Math.max(r, l + mn - 2); // 尽可能长的更新 r
}
return ans;
}
}
成绩记录
AK 了,还可以!