既然你可以获得幸福
那就去抓紧幸福
不然我们根本没法接受

t1, t2有些简单,t3有点意思(自定义比较函数),t4经典单调栈题
这场整体难度稍低,适合节日热身训练
模拟题吧,就是找不同,可以保存所有不同的索引,然后特例枚举2个不同的情况.
class Solution {
public boolean areAlmostEqual(String s1, String s2) {
List<Integer> arr = new ArrayList<>();
for (int i = 0; i < s1.length(); i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
arr.add(i);
}
}
if (arr.size() == 0) return true;
if (arr.size() == 1 || arr.size() > 2) return false;
int k1 = arr.get(0), k2 = arr.get(1);
return s1.charAt(k1) == s2.charAt(k2) && s1.charAt(k2) == s2.charAt(k1);
}
}简单模拟题,就是统计点的度(无向边的度)
class Solution {
public int findCenter(int[][] edges) {
int n = edges.length + 1;
int[] deg = new int[n+1];
for (int[] e: edges) {
deg[e[0]]++;
deg[e[1]]++;
}
for (int i = 1; i <= n; i++) {
if(deg[i] == n - 1) return i;
}
// unreachable
return 0;
}
}算是模拟+贪心,使用优先队列,但这题有点意思。
它不是按照 分子/分母 的最小值去贪心
而是递增量的概念
令,
则
然后根据 按大的排序
就是按照收益增量最大的贪心+模拟
class Solution {
public double maxAverageRatio(int[][] classes, int extraStudents) {
// 模拟吗?
int n = classes.length;
PriorityQueue<Integer> pp = new PriorityQueue<>((a, b) -> {
int[] t1 = classes[a], t2 = classes[b];
double res1 = (1l * (t1[0] + 1) * t1[1] - 1l * (t1[1] + 1) * t1[0]) * 1.0 / (1l * (t1[1] + 1) * t1[1]);
double res2 = (1l * (t2[0] + 1) * t2[1] - 1l * (t2[1] + 1) * t2[0]) * 1.0 / (1l * (t2[1] + 1) * t2[1]);
if (res1 != res2) return res1 < res2 ? 1 : -1;
return 0;
});
for (int i = 0; i < n; i++) {
pp.offer(i);
}
while (extraStudents > 0) {
int cur = pp.poll();
extraStudents--;
classes[cur][0]++;
classes[cur][1]++;
pp.offer(cur);
}
double acc = 0;
for (int[] c: classes) {
acc += 1.0 * c[0] / c[1];
}
return acc / n;
}
}这种多因子的最优解,常规的做法就是固定一个变量,然后求最优解。
那这题固定的变量是啥呢,就是枚举最小值,假设某个值为最小值,那就覆盖的区间越大越好
求这个区间范围最大,就是单调栈的经典使用了。
从左侧维护递增的单调栈,均摊找到左边界
同理从右侧维护递增的单调栈,均摊找到右边界
class Solution {
public int maximumScore(int[] nums, int k) {
// 单调栈应用
int n = nums.length;
int[] left = new int[n];
int[] right = new int[n];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && nums[stack.peek()] >= nums[i]) {
stack.pop();
}
if (stack.isEmpty()) left[i] = 0;
else left[i] = stack.peek() + 1;
stack.push(i);
}
stack.clear();
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && nums[stack.peek()] >= nums[i]) {
stack.pop();
}
if (stack.isEmpty()) right[i] = n - 1;
else right[i] = stack.peek() - 1;
stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (left[i] <= k && right[i] >= k) {
ans = Math.max(ans, (right[i] - left[i] + 1) * nums[i]);
}
}
return ans;
}
}