【LeetCode第 296 场周赛】?!?我AK了?!?
话不多说,先上图!!!
🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉
纪念第一次力扣AK!!!
🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉
快乐 总是 这么 短暂
让我们一起来体验这场美妙的算法之旅吧~~
文章目录
- 🏄 极大极小游戏
- 🏄 划分数组使最大差为 k
- 🏄 替换数组中的元素
- 🏄 设计一个文本编辑器
-
- 写在最后
神奇AK传送门
🏄 极大极小游戏
题目
思路
按照题目模拟
- 奇数取 m i n {min} min
- 偶数取 m a x {max} max
- 每轮结束后,原数组要改变为新数组
- l e n = = 1 {len == 1} len==1 退出循环
代码
class Solution {public: int minMaxGame(vector<int>& nums) { if(nums.size() == 1) return nums[0]; for (int i = 0; i < nums.size(); i++, i = 0) { int n = nums.size() / 2; vector<int> a(n, 0); for (int j = 0; j < n; j++) { if(j % 2 == 0) a[j] = min(nums[j * 2], nums[j * 2 + 1]); else a[j] = max(nums[j * 2], nums[j * 2 + 1]); } nums = a; if(n == 1) return nums[0]; } return -1; }};
🏄 划分数组使最大差为 k
题目
思路
题意:划分最少子序列,满足子序列中极大极小值只差不超过 k {k} k。
很显然,一眼贪心。因为能凑成一组的尽可能地都塞进一组中,这样是更优的。
从最大值来看,对于全局最大值 m a x {max} max,我一定会让所有在 [ m a x − k , m a x ] {[max - k, max]} [max−k,max] 之间的值分为一组。同理对于 m a x − k − 1 {max -k - 1} max−k−1 也是如此。
代码
class Solution {public: int partitionArray(vector<int>& a, int k) { sort(a.begin(), a.end()); int n = a.size(); int res = 1; int last = a[0], now = 0; for (int i = 1; i < n; i++) { now = a[i]; if(now - last <= k) continue; else { last = a[i]; res ++; } } return res; }};
🏄 替换数组中的元素
题目
思路
这题好写在于,题目给定了每一次操作 o p e r a t i o n s {operations} operations 中,要改变的值 p r e {pre} pre 一定存在于数组总,而改后的值 s u f {suf} suf 一定不存在于数组中。
由此我们直接唯一索引,开个全局 m a p {map} map,改要改的地方即可。
代码
class Solution {public: map<int, int> mp; vector<int> arrayChange(vector<int>& a, vector<vector<int>>& op) { for (int i = 0; i < a.size(); i++) { mp[a[i]] = i; } for (int i = 0; i < op.size(); i++) { int pre = op[i][0], suf = op[i][1]; int now = mp[pre]; a[mp[pre]] = suf; mp[suf] = now; } return a; }};
🏄 设计一个文本编辑器
题目
思路
一开始我思路从维护一个 d e q u e {deque} deque 变为两个 d e q u e {deque} deque。
后来发现,这不就是我之前做过的类似的一道题目嘛???而且数据范围是 ∑ 1 0 4 {\sum10^4} ∑104 次操作,每次最多还只是移动 40 40 40 次光标,以及取 10 10 10 个左侧字符。(这不纯暴力就能过的嘛)
用 两个栈 ( L 、 R L\ 、R L 、R )来模拟光标 之前 和 之后 的文本字符!!!
规定 光标 即为 L 、 R 之 间 L、R之间 L、R之间
-
addText(string text) addText(string\ text)addText(string text):【将 text texttext 添加到光标所在位置】
- 只向 L {L} L 加字符
-
deleteText(int k) deleteText(int\ k)deleteText(int k) :【删除光标左边 k kk 个字符】
- 只对 L {L} L 删字符
-
cursorLeft(int k) cursorLeft(int\ k)cursorLeft(int k):【将光标向左移动 k kk 次】
- 显然 L L L 顶部需要弹出 k k k 个到 R R R 中,并保证 L L L 非空
- 对于光标左侧
min(10, len)
个字符,我们直接暴力开一个栈 t m p tmp tmp, L L L弹出来到 t m p tmp tmp中,字符加给 r e s res res,然后 t m p tmp tmp 在弹回给 L L L - 注意 r e s res res 是逆序的
-
cursorRight(int k) cursorRight(int\ k)cursorRight(int k):【将光标向右移动 k kk 次】
- 显然 R R R 顶部需要弹出 k k k 个到 R R R 中,并保证 R R R 非空
- 同理
代码
class TextEditor {public: stack<char> L, R; TextEditor() { L = stack<char>(); R = stack<char>(); } // 只向 L 加字符 void addText(string text) { for (auto &x: text) { L.push(x); } } // 只对 L 删字符 int deleteText(int k) { int res = 0; while(L.size() && k) { L.pop(); res ++; k -= 1; } return res; } string cursorLeft(int k) { // 先将L中弹出道R中 while(L.size() && k) { char c = L.top(); L.pop(); R.push(c); k -= 1; } stack<char> tmp; int val = 10; string res = ""; // 在去弹出光标左侧的min(10, len)个字符 while(L.size() && val) { char c = L.top(); L.pop(); tmp.push(c); val -= 1; res += c; } reverse(res.begin(), res.end()); // 记得要逆序回来 // 返还给L while(tmp.size()) { L.push(tmp.top()); tmp.pop(); } return res; } string cursorRight(int k) { while(R.size() && k) { char c = R.top(); R.pop(); L.push(c); k -= 1; } string res = ""; stack<char> tmp; int val = 10; while(L.size() && val) { char c = L.top(); L.pop(); tmp.push(c); val -= 1; res += c; } while(tmp.size()) { L.push(tmp.top()); tmp.pop(); } reverse(res.begin(), res.end()); return res; }};
写在最后
感谢官方大大 给我一次 AK 的机会,虽然看到 评论区 都在 吐槽 这场 简单 ,但谁又能抵挡的住 AK 的 快乐 。
2022年6月5日12点11分 51银饰网