Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务活动详情
一、题目描述
给定一个数组,可以任意修改数组,使其变成一个 k 递增的数组,就是i,i+k,i+k+k这一串要是递增的。求最小操作次数。
数据范围
十万
二、思路分析
显然的一个事实是,可以把这个数组看成n个数组单独求解,因为它们之间没有任何关系。
问题也就转变成了,给定一个数组,求最小操作次数,将它变成不严格递增的数组。
怎么做呢?因为它要求的是不严格递增,也就是不下降,所以我们可以直接找出它最长的不下降子序列,这个就是最优的解,修改其他的即可(让不符合的元素变成和它旁边的一样)。
但是这仅局限于这道题,如果改成要严格递增的话,我们就会遇到新的问题,元素直接可能没有足够的空间去容纳我们修改,也就是直接找出最长不下降子序列并不能解决问题。这个问题我们暂时留着。
如何求最长不下降子序列呢? 这是一个经典的问题,有很多做法,最快的就是二分查找了。
三、AC代码
class Solution {
public:
int js(vector<int>& q){
int n = q.size();
vector<int > lis;
lis.push_back(999999999);
for (int i=0; i<n; i++) {
int p = upper_bound(lis.begin(), lis.end(), q[i]) - lis.begin();
if (p == lis.size()) lis.push_back(q[i]);
else lis[p] = q[i];
}
return n-lis.size();
}
int kIncreasing(vector<int>& arr, int k) {
int ans=0;
int n = arr.size();
for (int i=0; i<k; i++) {
int p=i;
vector<int > q;
while (p < n){
q.push_back(arr[p]);
p += k;
}
ans += js(q);
}
return ans;
}
};
四、总结
一开始卡在了如何修改才能使得它不下降,后来才发现,正是因为它不下降(不严格递增),使得我们可以很容易地去处理那些不符合的元素,也就使得我们可以粗暴地找出最长不下降子序列就可以了。