1.牛牛冲砖五
思路:
看懂样例即可。
代码:
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; int main() { int t; cin >> t; string str; while (t--) { int n, k; cin >> n >> k >> str; int ans = 0; for (int i = 0; i < n; i++) { if (str[i] == 'L')ans--; else { if (i >= 2 && str[i] == str[i - 1] && str[i] == str[i - 2]) { ans += k; } else ans++; } } cout << ans << endl; } }
2.最长无重复子数组
思路:
最古老的双指针。用两个指针维护一个没有重复元素的区间,基于计数。如果新加进来的一个元素导致了出现重复元素,那么我们就收紧左区间,直到没有重复元素为止。
代码:
class Solution { public: int maxLength(vector<int>& arr) { unordered_map<int,int> mp; int ans=1; for(int i=0,j=0;i<arr.size();i++){ mp[arr[i]]++; while(j<=i&&mp[arr[i]]>=2){ mp[arr[j]]--; j++; } ans=max(ans,i-j+1); } return ans; } };
3.重排字符串
思路:
基于贪心重构字符串。为了让字符串中的每个元素都“平均”的出现,我们可以每次然出现次数最多的字符和次多的字符去“凑成”一对。为什么要尽量把出现次数多的凑成一对呢?因为这些字符最危险,越是靠后处理这些字符,越容易出现相邻重复。用一个堆去维护当前每个字符出现的次数,当堆的元素大于1的时候,我们就可以取出最多的两个字符,这两个字符一定不同,我们把这两个字符依次加入到答案中。
如果最后堆的元素为空,说明正好处理完了。如果最后堆顶元素还剩下1,说明还有一种字符还没被“安排”。如果最后这个字符的次数还剩下超过1,那么说明一定会相邻。如果最后还剩一个元素,直接加到ans末尾就行了。
代码:
#include <iostream> #include<algorithm> #include<queue> using namespace std; typedef pair<int, int> PII; int main() { int n; string str; int a[26] = {0}; priority_queue<PII> q; cin >> n >> str; if (n == 1) { cout << "yes" << endl; cout << str << endl; return 0; } for (int i = 0; i < n; i++) { int u = str[i] - 'a'; a[u]++; } for (int i = 0; i < 26; i++) { if (a[i])q.push({ a[i], i }); } string ans = ""; while (q.size() > 1) { auto t1 = q.top(); q.pop(); auto t2 = q.top(); q.pop(); char u1 = t1.second + 'a'; char u2 = t2.second + 'a'; ans += u1; ans += u2; if (t1.first - 1 > 0)q.push({ t1.first - 1, u1 - 'a' }); if (t2.first - 1 > 0)q.push({ t2.first - 1, u2 - 'a' }); } if (!q.empty() && q.top().first >= 2) { cout << "no" << endl; } else { if (!q.empty()) { char u = q.top().second + 'a'; ans += u; } } cout << "yes" << endl; cout << ans << endl; } // 64 位输出请用 printf("%lld")