2021-03-14 第 232 场周赛
1790. 仅执行一次字符串交换能否使两个字符串相等
思路:签到题,把不相等的字符分别记录,判断是否反转后一致即可。
class Solution {
public boolean areAlmostEqual(String s1, String s2) {
int cnt = 0;
StringBuffer s3 = new StringBuffer();
StringBuffer s4 = new StringBuffer();
for(int i = 0;i < s1.length();i++) {
if(s1.charAt(i) != s2.charAt(i)) {
s3.append(s1.charAt(i));
s4.append(s2.charAt(i));
}
}
return s3.length() == 0 ||
(s3.length() == 2 && s3.toString().equals(s4.reverse().toString()));
}
}
1791. 找出星型图的中心节点
思路:找出出现了n次的数即可
class Solution {
int mx = (int) (1e5 + 10);
int[] cnt = new int[mx];
public int findCenter(int[][] edges) {
int n = edges.length, res = 0;
for(int[] e:edges) {
cnt[e[0]]++;
cnt[e[1]]++;
}
for(int i = 1;i < mx;i++) {
if(cnt[i] == n) {
res = i;
break;
}
}
return res;
}
}
1792. 最大平均通过率
思路:贪心的思想,假设每个班级的通过率为 r i r_i ri,那么平均通过率为 ∑ i = 1 n r i n \frac{\sum_{i=1}^n{r_i}}{n} n∑i=1nri。而又可以知道, x + 1 y + 1 ≥ x y \frac{x+1}{y+1} \geq \frac{x}{y} y+1x+1≥yx,说明每个加进来额外的学生都会使得原先班级的通过率增加或者不变。
设增加一个学生后该班级通过率的增量为 d i f f = x + 1 y + 1 − x y diff = \frac{x+1}{y+1} - \frac{x}{y} diff=y+1x+1−yx,则我们要选择增量最大的班级来分配额外的学生。这里可以使用最大堆来做,堆顶的班级就是增量最大的班级。
class Solution {
public double maxAverageRatio(int[][] classes, int extraStudents) {
int n = classes.length;
double rate = 0;
// 维护增量最大的最大堆
PriorityQueue<double[]> q = new PriorityQueue<>(new Comparator<double[]>() {
@Override
public int compare(double[] o1, double[] o2) {
double diff1 = (o1[0]+1)/(o1[1]+1) - (o1[0]/o1[1]);
double diff2 = (o2[0]+1)/(o2[1]+1) - (o2[0]/o2[1]);
if(diff2 > diff1)
return 1;
return -1;
}
});
for(int[] c:classes) {
q.offer(new double[]{c[0], c[1]});
}
// 挑选出增量最大的班级
while(extraStudents-- > 0) {
double[] c = q.poll();
c[0] += 1;
c[1] += 1;
q.offer(c);
}
while(q.size() > 0) {
double[] c = q.poll();
rate += (c[0] / c[1]);
}
return rate/n;
}
}
1793. 好子数组的最大分数
思路:这道压轴题还是比较简单的。只需要遍历数组,将每个值作为最小值,找出以该值为最小值的左右边界分别在什么位置,然后比较得出答案即可。
class Solution {
public int maximumScore(int[] nums, int k) {
int n = nums.length, res = 0;
int[] l = new int[n], r = new int[n];
l[0] = -1; r[n-1] = n;
for(int i = 1;i < n;i++) {
int j = i-1;
while(j != -1 && nums[j] >= nums[i]) {
j = l[j];
}
l[i] = j;
}
for(int i = n-2;i >= 0;i--) {
int j = i+1;
while(j != n && nums[j] >= nums[i]) {
j = r[j];
}
r[i] = j;
}
for(int i = 0; i < n;i++) {
int left = l[i], right = r[i];
if(left+1 <= k && right-1 >= k) {
res = Math.max(res, (right-left-1)*nums[i]);
}
}
return res;
}
}