这次周赛应该是今年最简单的一次了,然而我还是没有AK
下面总结以下这次错误与教训。
第一题
(题号5701):
简单题,但是WA了一次
一开始以为找到相同字母换一下就完事了,交了一发才知道事情不简单。
然后开始统计不同字母的个数,
若为1或者大于2,则肯定交换不了;
若为0则肯定交换的了;
若为2则交换两个不同下标,再看看两个字符串是否相等。
代码如下:
class Solution {
public:
bool areAlmostEqual(string s1, string s2) {
int n = s1.size();
vector<int> a;
for(int i = 0; i < n; ++i){
if(s1[i] == s2[i]) continue;
a.push_back(i);
}
if(a.size() == 0) return true;
if(a.size() == 1 || a.size() > 2) return false;
swap(s1[a[0]], s1[a[1]]);
if(s1[a[0]] == s2[a[0]] && s1[a[1]] == s2[a[1]]) return true;
return false;
}
};
第二题
(题号5702):nc题
这数据范围给的,太nc了出题人。
既然edges.length == n - 1
那么我只需要找出数组前两行相等的数就行
class Solution {
public:
int findCenter(vector<vector<int>>& edges) {
int a = edges[0][0], b = edges[0][1], c = edges[1][0], d = edges[1][1];
if(a == c || a == d) return a;
return b;
}
};
第三题 (优先队列+自定义排序)
(编号5703 – 优先队列):
数据范围10^5:nlogn
优先队列
主要是卡在了如何给优先队列写自定义排序,找了好久博客
这里附上两种写法:
//写法一:
struct node{
int u;
long long dis;
bool operator < (const node &x) const{
return dis > x.dis;
}
};
//写法二:
struct cmp1{
bool operator () (比较数据类型 &a1, 比较数据类型 &a2){
return 比较方法;
}
}
思路:
优先队列排序:分子分母同时+1,增量最大的班级就加上一个同学,然后重新排序,直到加完所有同学
class Solution {
public:
typedef struct _A{ //定义类型
double a;
double b;
}A;
struct cmp1{ //自定义比较
bool operator ()(A &a1, A &a2){
double t1 = (a1.a + 1) / (a1.b + 1) - a1.a / a1.b;
double t2 = (a2.a + 1) / (a2.b + 1) - a2.a / a2.b;
return t1 < t2;
}
};
double maxAverageRatio(vector<vector<int>>& classes, int extraStudents) {
int n = classes.size();
priority_queue<A, vector<A>, cmp1> q1;
for(int i = 0; i < n; ++i){ //入队
A t;
t.a = classes[i][0], t.b = classes[i][1];
q1.push(t);
}
while(extraStudents != 0){ //加增量
A t = q1.top();
q1.pop();
t.a += 1, t.b += 1;
q1.push(t);
extraStudents--;
}
double cnt = 0;
while(!q1.empty()){ //出队统计
A t = q1.top();
q1.pop();
cnt += t.a / t.b;
}
return cnt / n;
}
};
第四题 (双指针贪心)
(编号5704–双指针贪心):
数据范围 10^5 : n 或 nlogn
题解链接: 点这里.
(题解为本人所写)
思路 :
区间必须得包含下标k
那么可以从k开始向左向右寻找以 nums[k] 为最小值的好子数组:
1.nums[r] >= nums[k] : r++
2.nums[l] >= nums[k] : l–
直到左右边界都出现比nums[k]小的数,此时计算最大可能分数 res = (r - l - 1) * nums[k]
同时更新 nums[k] 为左右边界中的较大者,继续寻找以 nums[k] 为最小值的好子数组
直到 l < 0 && r == n
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
int maximumScore(vector<int>& nums, int k) {
int l = k, r = k, n = nums.size(), res = 0; //定义左右边界l r,最大可能分数res
while(1){
while(r < n && nums[r] >= nums[k]) r++; //向右寻找以nums[k]为最小值的好子数组
while(l >= 0 && nums[l] >= nums[k]) l--; //向左寻找以nums[k]为最小值的好子数组
res = max(res, (r - l - 1) * nums[k]); //更新最大可能分数
if(l < 0 && r == n) break; //遍历完数组,直接退出循环
if(l >= 0 && r < n) nums[k] = max(nums[l], nums[r]); //更新nums[k] 为左右边界中的较大者
else if(l < 0) nums[k] = nums[r]; //左边遍历完了,更新nums[k]为右边界
else nums[k] = nums[l]; //右边遍历完了,更新nums[k]为左边界
}
return res;
}
};
一开始为什么错:
这里判断更新条件根本就没必要,当初不知道为什么脑子想抽了。
因为这里的l与r左右边界都是不算进好子数组的,所以无论l,r在不在数组范围,好子数组长度都是(r - l - 1)