第 219 场周赛
题目1:5625. 比赛中的配对次数
思路:模拟
代码:
class Solution {
public:
int numberOfMatches(int n) {
int ret = 0;
while(n > 1) {
int cur = n / 2; // 比赛次数,也是晋级队伍数量
ret += cur; // 计入比赛场次
n -= cur * 2; // 轮空队伍数量
n += cur; // 晋级队伍 + 轮空队伍 = 剩余队伍数量
}
return ret;
}
};
复杂度分析:
时间复杂度为 O ( l g n ) O(lgn) O(lgn),空间复杂度为 O ( 1 ) O(1) O(1)。
题目2:5626. 十-二进制数的最少数目
思路:模拟
求字符串中出现的最大的数字即可
代码:
class Solution {
public:
int minPartitions(string n) {
int ret = 0;
for(char c : n) {
ret = max(ret, c - '0');
}
return ret;
}
};
复杂度分析:
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。
题目3:5627. 石子游戏 VII
思路:动态规划
对于两个选手,希望的都是尽可能扩大两人得分之间的差值,维护二维数组 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示在 [ i , j ] [i, j] [i,j] 区间内删除最左边或者最右边的数后得分的更大差值。如果删除 s t o n e s [ i ] stones[i] stones[i],得分为 [ i + 1 , j ] [i + 1, j] [i+1,j] 区间的石子值总和(可以提前维护前缀和通过 O ( 1 ) O(1) O(1) 得到),然后第二个人能得到的最大差值为 d p [ i + 1 ] [ j ] dp[i + 1][j] dp[i+1][j],同理,如果删除 s t o n e s [ j ] stones[j] stones[j],得分为 [ i , j − 1 ] [i, j - 1] [i,j−1] 区间的石子值总和,第二个人能得到的最大差值为 d p [ i ] [ j − 1 ] dp[i][j - 1] dp[i][j−1]。
由于 Alice 希望提高差值,Bob也希望提高差值,两人希望的差值方向不同,所以更新时需要比较得分与下一个人差值的差,也即 d p [ i ] [ j ] = m a x ( s c o r e 1 − d p [ i + 1 ] [ j ] , s c o r e 2 − d p [ i ] [ j − 1 ] ) dp[i][j] = max(score_1 - dp[i + 1][j], score_2 - dp[i][j - 1]) dp[i][j]=max(score1−dp[i+1][j],score2−dp[i][j−1])
由于一个区间的差值 d p [ i ] [ j ] dp[i][j] dp[i][j] 是由更小的区间内的差值得来的,所以遍历更新是要维护区间长度从小到大。
特别地,$ i = j$ 时,说明当前数组只剩下一个元素,此时删除该元素无法得分,所以初始化 d p [ i ] [ i ] = 0 dp[i][i] = 0 dp[i][i]=0。
代码:
class Solution {
public:
int stoneGameVII(vector<int>& a) {
int n = a.size();
vector<int> v(n + 1, 0);
for(int i = 1; i <= n; i++) v[i] = v[i - 1] + a[i - 1];
vector<vector<int>> dp(n, vector<int>(n, 0));
for(int k = 1; k < n; k++) {
for(int i = 0; i < n; i++) {
int j = i + k;
if(j == n) break;
dp[i][j] = max(v[j + 1] - v[i + 1] - dp[i + 1][j],\
v[j] - v[i] - dp[i][j - 1]);
}
}
return dp[0][n - 1];
}
};
复杂度分析:
时间复杂度为 O ( n 2 ) O(n^2) O(n2),相当于遍历了所有子区间,共有 n + n − 1 + . . . + 1 = n ( n + 1 ) 2 n + n - 1 + ... + 1 = \frac{n(n + 1)}{2} n+n−1+...+1=2n(n+1) 个子区间
空间复杂度为 O ( n 2 ) O(n^2) O(n2),维护了二维数组
题目4:5245. 堆叠长方体的最大高度
思路:动态规划
如果两个长方体可以拼接,根据题意,长宽高都需要满足同样的大小关系,则不管从什么方向都可以拼接。为了提高拼接后的长度,我们只需要将这三个指标中较长的一个单独提取出来作为高。
因此,我们先对每个长方体进行长宽高排序(将最长的作为高),然后对所有长方体进行排序,再遍历更新最大值即可(类似于最大上升子序列)
代码:
class Solution {
public:
int maxHeight(vector<vector<int>>& a) {
int n = a.size();
for (auto &aa : a) sort(aa.begin(), aa.end());
sort(a.begin(), a.end());
vector<int> dp(n);
int ret = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) {
if(a[j][1] <= a[i][1] && a[j][2] <= a[i][2]) {
dp[i] = max(dp[i], dp[j]);
}
}
dp[i] += a[i][2]; // 加上高度
ret = max(ret, dp[i]);
}
return ret;
}
};
复杂度分析:
时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( n 2 ) O(n^2) O(n2)