2278. Percentage of Letter in String
Analysis
第一个题比较简单,统计下次数,再算一下就可以了。
Code
这是当时提交的代码:1
2
3
4
5
6
7
8
9
10class Solution {
public:
int percentageLetter(string s, char letter) {
int cnt = 0;
for(char c: s) {
if(c == letter) cnt++;
}
return cnt * 100 / s.length();
}
};
2280. Minimum Lines to Represent a Line Chart
Analysis
这是第三个题,但是是自己第二个提交的题。
题意不难理解,就是找出整个折线图中所有斜率不同的线段。
当时的思路是,用一个变量统计线段数,挨个算相邻点构成的直线的斜率,相同就忽略,不同就加 1。本来一开始是打算直接用 set 的,但是后来想到,斜率相等但不是相邻的线段,是不同的两条线段。
Code
这是当时提交的代码,死在 58 个用例了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Solution {
public:
int minimumLines(vector<vector<int>>& stockPrices) {
int size = stockPrices.size();
if(size == 1) return 0;
int cnt = 1;
int prek = (stockPrices[1][1] - stockPrices[0][1]) / (stockPrices[1][0] - stockPrices[0][0]);
int curk;
sort(stockPrices.begin(), stockPrices.end());
for(int i = 2; i < size; i++) {
curk = (stockPrices[i][1] - stockPrices[i - 1][1]) / (stockPrices[i][0] - stockPrices[i - 1][0]);
if(curk != prek) cnt++;
prek = curk;
}
return cnt;
}
};
上面的代码有点小问题,那就是在开始计算之前,就应该排序。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Solution {
public:
int minimumLines(vector<vector<int>>& stockPrices) {
int size = stockPrices.size();
if(size == 1) return 0;
sort(stockPrices.begin(), stockPrices.end());
int cnt = 1;
int prek = (stockPrices[1][1] - stockPrices[0][1]) / (stockPrices[1][0] - stockPrices[0][0]);
int curk;
for(int i = 2; i < size; i++) {
curk = (stockPrices[i][1] - stockPrices[i - 1][1]) / (stockPrices[i][0] - stockPrices[i - 1][0]);
if(curk != prek) cnt++;
prek = curk;
}
return cnt;
}
};
换了下位置,又被卡在第 62 个用例了。
看了下题解,发现这是个精度问题,直接用除法会损失小数,造成本不该相等的斜率相等了,这样就漏解了。将int
换成double
会被卡在第 80 个用例。幸运的是,C++ 提供了long double
这种 16 个字节的基本类型,就可以直接用除法了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Solution {
public:
int minimumLines(vector<vector<int>>& stockPrices) {
int size = stockPrices.size();
if(size == 1) return 0;
sort(stockPrices.begin(), stockPrices.end());
int cnt = 1;
long double prek = (long double)(stockPrices[1][1] - stockPrices[0][1]) / (stockPrices[1][0] - stockPrices[0][0]);
long double curk;
for(int i = 2; i < size; i++) {
curk = (long double)(stockPrices[i][1] - stockPrices[i - 1][1]) / (stockPrices[i][0] - stockPrices[i - 1][0]);
if(curk != prek) cnt++;
prek = curk;
}
return cnt;
}
};
但这个题,还可以从判断 3 点是否共线的角度思考,也就是向量的叉积。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution {
public:
int minimumLines(vector<vector<int>>& stockPrices) {
int size = stockPrices.size();
if(size == 1) return 0;
sort(stockPrices.begin(), stockPrices.end());
int cnt = 1;
for(int i = 2; i < size; i++) {
long long x1 = stockPrices[i][0] - stockPrices[i - 1][0], y1 = stockPrices[i][1] - stockPrices[i - 1][1];
long long x2 = stockPrices[i - 1][0] - stockPrices[i - 2][0], y2 = stockPrices[i - 1][1] - stockPrices[i - 2][1];
if(y1 * x2 != y2 * x1) cnt++;
}
return cnt;
}
};
当然,判断 3 点是否共线还可以计算这 3 个点组成的三角形面积是否为 0,而三角形的面积计算公式既可以用向量,也可以用海伦凯勒公式。
2279. Maximum Bags With Full Capacity of Rocks
Analysis
这是第二个题,一看就是背包问题,基本没做过类似的题,就直接弃了。上一次做的时候,是春赛的第二题,这次得把两个题都搞定。
仔细一看这个题,实际上是个贪心的题目。为了得到装满石头的背包的最大数量,最开始放石头的背包一定是快装满的背包。
Code
没想到回过神来想到的第一种解法是重新构造结构体在排序...1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class Solution {
public:
struct package{
long long remain, size, now;
package(): remain(0), size(0), now(0){}
};
int maximumBags(vector<int>& capacity, vector<int>& rocks, int additionalRocks) {
int n = capacity.size();
package pak[n];
for(int i = 0; i < n; i++) {
pak[i].size = capacity[i];
pak[i].now = rocks[i];
pak[i].remain = pak[i].size - pak[i].now;
}
sort(pak, pak + n, [](package a, package b) { return a.remain < b.remain; });
int cnt = 0;
for(int i = 0; i < n; i++) {
if(pak[i].remain != 0) {
additionalRocks -= pak[i].remain;
if(additionalRocks >= 0) cnt++;
else break;
} else if(pak[i].remain == 0) cnt++;
}
return cnt;
}
};
实际上用 multiset 就可以了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Solution {
public:
int maximumBags(vector<int>& capacity, vector<int>& rocks, int additionalRocks) {
multiset<int> remains;
int n = capacity.size();
for(int i = 0; i < n; i++) {
remains.insert(capacity[i] - rocks[i]);
}
int cnt = 0;
for(auto &i: remains) {
if(i != 0) {
additionalRocks -= i;
if(additionalRocks >= 0) cnt++;
else break;
} else if(i == 0) cnt++;
}
return cnt;
}
};
使用 multiset 容器的时间、空间消耗都很大,不如直接换成 vector,然后排序。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Solution {
public:
int maximumBags(vector<int>& capacity, vector<int>& rocks, int additionalRocks) {
vector<int> remains;
int n = capacity.size();
for(int i = 0; i < n; i++) {
remains.push_back(capacity[i] - rocks[i]);
}
sort(remains.begin(), remains.end());
int cnt = 0;
for(auto &i: remains) {
if(i != 0) {
additionalRocks -= i;
if(additionalRocks >= 0) cnt++;
else break;
} else if(i == 0) cnt++;
}
return cnt;
}
};
果然,快多了...
这么一看的话,这个题当时是可以做出来的,没经过仔细思考,直接认为这个题需要用 dfs 来求解...大意失荆州了啊~
2281. Sum of Total Strength of Wizards
Analysis
题意不难理解,就是算出所有子数组最小值与对应的和的积然后再相加。
参考思路:计算每个数字作为最小值的贡献。
如这篇题解所说先做一下 907 比较好。仔细拆分下来这个题实际上是前缀和 + 单调栈 + 数学,不过自己能单独做出来,估计得很长一段时间后了。
Code
1 | class Solution { |
Summary
这次周赛大意了,本来第二个题可以做的,结果把时间都花在第三个题上了(大致思路是对的,但没做出来)。第二题的主要问题是,搞错题目类型了,然后就放掉了...
第三题其实是每日一题见过的类似题目,但是升级到中等题就做不出来了...
第四题是个很不错的单调栈 + 前缀和的综合题,花时间把这个题吃透应该能有所值。
总之,这周的周赛有点亏😭。