LeetCode第 75 场双周赛题解
2220. 转换数字的最少位翻转次数
题目描述:给你两个整数\(a , b\),每次可以翻转a
的一个二进制位,问最少需要多少次才可以将a
变成b
。
思路:显然先将a , b
异或之后统计异或后的数字的二进制位中1
的个数。
时间复杂度:\(O(logn)\)
参考代码:
class Solution {
public:
int minBitFlips(int start, int goal) {
start ^= goal;
int res = 0;
for(int i = 30 ; i >= 0 ; --i) res += (start >> i) & 1;
return res;
}
};
2221. 数组的三角和
题目描述:给你一个长度为\(n - 1\)的数组\(nums\),构造一个长度为\(n - 1\)的新数组\(a\),满足\(a_i = nums_i + nums_{i + 1} \forall 1 \leq i < n\)。若递归构造,直到新数组的长度变为\(1\),问这个最终的数组的值模10
后的值是多少。
思路:根据题意模拟即可
时间复杂度:\(O(n^2)\)
参考代码:
class Solution {
public:
int triangularSum(vector& nums) {
int res = 0, n = nums.size();
for(int i = n ; i >= 1 ; --i){
for(int j = 0 ; j < i ; ++j){
res += nums[j];
if(j < i - 1) nums[j] = (nums[j] + nums[j + 1]) % 10;
}
}
return nums[0];
}
};
6035. 选择建筑的方案数
题目描述:给你一个二进制串,问你有多少长度为\(3\)的子串为101
或者010
。
思路:赛时思路参考了115. 不同的子序列
时间复杂度:\(O(n)\)
参考代码:
class Solution {
public:
long long numberOfWays(string s) {
int n = s.size();
vector> f(n + 1 , vector(4 , 0));
auto cal = [&](string t)->long long{
int n = s.size(), m = t.size();
for(int i = 0 ; i <= n ; ++i) f[i][0] = 1;
for(int i = 1 ; i <= n ; ++i){
char c = s[i - 1];
for(int j = 1 ; j <= m ; ++j){
if(c == t[j - 1]) f[i][j] = f[i - 1][j] + f[i - 1][j - 1];
else f[i][j] = f[i - 1][j];
}
}
return f[n][m];
};
return cal("010") + cal("101");
}
};
2223. 构造字符串的总得分和
题目描述:给你一个长度为\(n\)的字符串\(s\),对于它的每一个后缀,其得分为该后缀与原串的最长公共前缀的长度,求\(s\)的得分。
思路:\(z\)函数的模板题目,注意\(z_0 = n\),具体证明可以看z函数(扩展KMP)。
时间复杂度:\(O(n)\)
参考代码:
class Solution {
private:
public:
long long sumScores(string s) {
int n = s.size();
vectorz(n, 0);
auto zFuncation = [&](int len) {
for (int i = 1, lr = 0, rs = 0; i < len; ++i) {
if (i <= rs && z[i - lr] < rs - i + 1) z[i] = z[i - lr];
else {
z[i] = max(0, rs - i + 1);
while (i + z[i] < len && s[z[i]] == s[i + z[i]]) ++z[i];
}
if (i + z[i] - 1 > rs) lr = i, rs = i + z[i] - 1;
}
return;
};
zFuncation(n);
long long res = 0;
for (auto& val : z) res += val;
res += n;
return res;
}
};