思维|栈
lc2216
lc1209
用数组记录字符连续重复次数
一旦达到k就删除对应子串并回退索引
最终得到去重后的字符串。
class Solution {
public:
string removeDuplicates(string s, int k) {
vector<int> cnt(s.size(), 0);
for (int i = 0; i < s.size(); ++i)
{
// 首个元素或者不重复
if (i == 0 || s[i] != s[i-1])
{
cnt[i] = 1;
}
else
{
// 发现重复,那就是基于之前cnt+1
cnt[i] = cnt[i-1] + 1;
if (cnt[i] == k)
{
s.erase(i-k+1, k);
i -= k;
}
}
}
return s;
}
};
lc910
枚举 截断点 + 小的变大,大的变小
先排序数组,然后遍历数组,通过调整前部分元素加 k 、后部分元素减 k ,找所有可能区间的最小差值
class Solution {
public:
int smallestRangeII(vector<int>& nums, int k) {
ranges::sort(nums);
int ans = nums.back() - nums[0];
for (int i = 1; i < nums.size(); i++) {
int mx = max(nums[i - 1] + k, nums.back() - k);
int mn = min(nums[0] + k, nums[i] - k);
ans = min(ans, mx - mn);
}
return ans;
}
};
lc1775
贪心求op 关注区间 不用关注具体值
完美优雅的抽象...
先判断能否通过调整使两数组和相等
若能,统计两数组元素可产生的最大变化量,从大到小累加变化量
来计算让差值为0所需的最少操作次数。
class Solution {
public:
int minOperations(vector<int> &nums1, vector<int> &nums2)
{
if (6 * nums1.size() < nums2.size() || 6 * nums2.size() < nums1.size())
return -1; // 优化
int d = accumulate(nums2.begin(), nums2.end(), 0) - accumulate(nums1.begin(), nums1.end(), 0);
if (d < 0)
{
d = -d;
swap(nums1, nums2); // 统一让 nums1 的数变大,nums2 的数变小
}
int cnt[6]{}; // 统计每个数的最大变化量
for (int x: nums1) ++cnt[6 - x]; // nums1 的变成 6
for (int x: nums2) ++cnt[x - 1]; // nums2 的变成 1
for (int i = 5, ans = 0;; --i) { // 从大到小枚举最大变化量 5 4 3 2 1
if (i * cnt[i] >= d) // 可以让 d 变为 0
return ans + (d + i - 1) / i;
ans += cnt[i]; // 需要所有最大变化量为 i 的数
d -= i * cnt[i];
}
}
};