【2022/04/17-第289场单周赛】 复盘

Q1.计算字符串的数字和
Q1链接
题意:字符串长度大于k时,每k个字符都各自转换为对应个位数然后相加,结果转化成对应字符串,然后所有结果字符串加到一起代替原字符串。直到字符串长度小于等于k为止。
class Solution {
public:
string digitSum(string s, int k) {
while(s.size() > k){
int cnt = 0, x = 0;
string temp, ss;
for(auto i : s){
x += i - '0';
++cnt;
if(cnt == k){
cnt = 0;
ss += to_string(x);
x = 0;
}
}
if(cnt) ss += to_string(x);
s = ss;
}
return s;
}
};
水题。
Q2.完成所有任务需要的最少轮数
Q2链接
题意:某个任务的数量x为1就直接返回-1,否则结果加上(x + 2) / 3。
class Solution {
public:
int minimumRounds(vector<int>& tasks) {
unordered_map<int, int> mp;
for(auto i : tasks) ++mp[i];
int ret = 0;
for(auto i : mp){
if(i.second == 1) return -1;
else ret += ((i.second + 2) / 3);
}
return ret;
}
};
水题。
Q3.转角路径的乘积中最多能有几个尾随零
Q3链接
题意:对于每条只有一个转角的路径,把路径上所有数总共的2的因子个数和总共的5的因子个数求出来,然后返回两者较小值。
用前缀和维护每个位置向上和向左路径中2和5的因子个数。
class Solution {
public:
int maxTrailingZeros(vector<vector<int>>& g) {
int m = g.size(), n = g[0].size();
vector<vector<int>> m2(m, vector<int> (n, 0)), m5(m, vector<int> (n, 0));
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
int p2 = 0, p5 = 0;
while(g[i][j] % 2 == 0){
g[i][j] /= 2;
++p2;
}
while(g[i][j] % 5 == 0){
g[i][j] /= 5;
++p5;
}
m2[i][j] = p2;
m5[i][j] = p5;
}
}
vector<vector<int>> ps2h(m + 1, vector<int> (n + 1, 0)), ps5h(m + 1, vector<int> (n + 1, 0)), ps2s(m + 1, vector<int> (n + 1, 0)), ps5s(m + 1, vector<int> (n + 1, 0));
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
ps2h[i + 1][j + 1] = ps2h[i + 1][j] + m2[i][j];
ps5h[i + 1][j + 1] = ps5h[i + 1][j] + m5[i][j];
ps2s[i + 1][j + 1] = ps2s[i][j + 1] + m2[i][j];
ps5s[i + 1][j + 1] = ps5s[i][j + 1] + m5[i][j];
}
}
int ret = 0;
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
int zs2 = ps2h[i + 1][j + 1] + ps2s[i + 1][j + 1] - m2[i][j], zs5 = ps5h[i + 1][j + 1] + ps5s[i + 1][j + 1] - m5[i][j];
ret = max(ret, min(zs2, zs5));
int zx2 = ps2h[i + 1][j + 1] + ps2s[m][j + 1] - ps2s[i + 1][j + 1], zx5 = ps5h[i + 1][j + 1] + ps5s[m][j + 1] - ps5s[i + 1][j + 1];
ret = max(ret, min(zx2, zx5));
int yx2 = ps2h[i + 1][n] - ps2h[i + 1][j + 1] + ps2s[m][j + 1] - ps2s[i + 1][j + 1] + m2[i][j], yx5 = ps5h[i + 1][n] - ps5h[i + 1][j + 1] + ps5s[m][j + 1] - ps5s[i + 1][j + 1] + m5[i][j];
ret = max(ret, min(yx2, yx5));
int ys2 = ps2h[i + 1][n] - ps2h[i + 1][j + 1] + ps2s[i + 1][j + 1], ys5 = ps5h[i + 1][n] - ps5h[i + 1][j + 1] + ps5s[i + 1][j + 1];
ret = max(ret, min(ys2, ys5));
}
}
return ret;
}
};
前缀和下标处理还是挺麻烦的。
前缀和计算有优化空间。
Q4.相邻字符不同的最长路径
Q4链接
题意:在一张图中,找到相邻字母不同的最长路径。
可以利用树的直径求法。
class Solution {
public:
vector<int> adj[100010];
int visit1[100010], temp, visit2[100010], f, maxd = 0;
void DFS1(int s, int depth){
if(depth > maxd){
maxd = depth;
f = s;
}
for(auto i : adj[s]){
if(!visit1[i]){
visit1[i] = 1;
DFS1(i, depth + 1);
}
}
}
void DFS2(int s, int depth){
if(depth > maxd){
maxd = depth;
}
for(auto i : adj[s]){
if(!visit2[i]){
visit2[i] = 1;
DFS2(i, depth + 1);
}
}
}
int longestPath(vector<int>& parent, string s) {
int n = parent.size(), ret = 1;
memset(visit1, 0, 100010);
memset(visit2, 0, 100010);
for(int i = 0; i < n; ++i) adj[i].clear();
for(int u = 1; u < n; ++u){
int v = parent[u];
if(s[u] != s[v]){
adj[u].push_back(v);
adj[v].push_back(u);
}
}
for(int i = 0; i < n; ++i){
if(!visit1[i]){
visit1[i] = 1;
maxd = 0;
DFS1(i, 1);
visit2[f] = 1;
maxd = 0;
DFS2(f, 1);
ret = max(ret, maxd);
}
}
return ret;
}
};
浙公网安备 33010602011771号