目录
- 1.mari和shiny
- 1.题目链接
- 2.算法原理详解 && 代码实现
- 2.重排字符串
- 1.题目链接
- 2.算法原理详解 && 代码实现
1.mari和shiny
1.题目链接
- mari和shiny
2.算法原理详解 && 代码实现
-
自己的版本:三层循环暴力枚举 --> 超时 --> 40%
#include <iostream> #include <string> using namespace std; int main() { int n = 0, cnt = 0; cin >> n; string str; cin >> str; // 三层暴力枚举 for(int i = 0; i < n - 2; i++) { if(str[i] != 's') { continue; } for(int j = i + 1; j < n - 1; j++) { if(str[j] != 'h') { continue; } for(int k = j + 1; k < n; k++) { if(str[k] != 'y') { continue; } else { cnt++; } } } } cout << cnt << endl; return 0; }
-
优化版本:动态规划 – 多状态的线性dp
-
状态表示:
s[i]
:[0, i]
区间内,有多少个"s"
h[i]
:[0, i]
区间内,有多少个"sh"
y[i]
:[0, i]
区间内,有多少个"shy"
-
状态转移方程:
-
初始化:
s[0] = str[0] == 's' ? 1 : 0, h[0] = y[0] = 0;
-
空间优化:
#include <iostream> #include <string> using namespace std; int main() { int n = 0; string str; cin >> n >> str; long long s = 0, h = 0, y = 0; for(int i = 0; i < n; i++) { char ch = str[i]; if(ch == 's') { s++; } else if(ch == 'h') { h += s; } else if(ch == 'y') { y += h; } } cout << y << endl; return 0; }
-
2.重排字符串
1.题目链接
- 重排字符串
2.算法原理详解 && 代码实现
- 自己的版本:33.33%
#include <iostream> #include <string> #include <unordered_set> #include <unordered_map> using namespace std; int main() { int n = 0; string str; cin >> n >> str; unordered_map<char, int> hash; unordered_set<char> deDup; int maxLen = 0; char maxCh = 'a'; for(const auto& ch : str) { deDup.insert(ch); hash[ch]++; int tmp = max(maxLen, hash[ch]); if(tmp > maxLen) { maxLen = tmp; maxCh = ch; } } bool flag = true; if(maxLen > n / 2 + 1) { flag = false; cout << "no" << endl; // 一个字符串的数量如果超过n / 2 + 1,则肯定不可以 } // 到这里之后,肯定都是可以的 // 这里的重组方法有失偏颇 string ret; ret += maxCh, hash[maxCh]--; while(!hash.empty()) { for(const auto& ch : deDup) { if(hash.count(ch)) { ret += ch; hash[ch]--; if(hash[ch] == 0) { hash.erase(ch); } } } } if(flag) { cout << "yes" << endl << ret << endl; } return 0; }
- 优化版本:贪心 + 构造
- 不能重排: x > ( n + 1 ) / 2 x > (n + 1) / 2 x>(n+1)/2
- 能重排:
- 每次去处理一批相同的字符 --> [自己的版本没意识到的思路]
- 优先处理出现次数最多的字符
- 每次摆放的时候,间隔一个格子
- 重点:手动控制间隔 --> [自己的版本没能实现的]
#include <iostream> #include <string> #include <unordered_map> using namespace std; int main() { int n = 0; string str; cin >> n >> str; unordered_map<char, int> hash; int maxLen = 0; char maxCh = 'a'; for(const auto& ch : str) { if(++hash[ch] > maxLen) { maxLen = hash[ch]; maxCh = ch; } } if(maxLen > (n + 1) / 2) { cout << "no" << endl; } else { int index = 0; string ret; ret.resize(n); // 先去拜访出现次数最多的 while(maxLen--) { ret[index] = maxCh; index += 2; } hash.erase(maxCh); // 再摆放剩下的 for(auto& it : hash) { if(it.second) { while(it.second--) { if(index >= n) { index = 1; } ret[index] = it.first; index += 2; } } } cout << "yes" << endl << ret << endl; } return 0; }