灵神题单滑动窗口可获得的最大点数(洛谷1423)思考题题解
解题思路
这道题的原题大致意思可以看上面链接,有一种做法是逆向思维,也就是,只能从首部或者尾部取一个数字,那么剩下的部分肯定是连续的,假设数组长度为n,要取的数字的个数为k,也就是求数组中
n-k个连续子数组的最小值,用总和减去最小值就可以得到最终的答案
原题逆向思维解法代码
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int s=0,ans=INT_MAX;
int nn=cardPoints.size();
int n=nn-k;
if(n==0){
return accumulate(cardPoints.begin(),cardPoints.end(),0);
}
for(int i=0;i<cardPoints.size();i++){
s+=cardPoints[i];
if(i-n+1<0)continue;
ans=min(ans,s);
s-=cardPoints[i-n+1];
}
return accumulate(cardPoints.begin(),cardPoints.end(),0)-ans;
}
};
原题灵神解法代码(两种)
思考题解法
同理,思考题我们也可以这样做,就是求这个数组,这整个数组的最小字段和,后来了解,这种做法其实有一个专有的名字叫做Kadane算法
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int cur=0,mn=0;
int n=cardPoints.size();
int s=accumulate(cardPoints.begin(),cardPoints.end(),0);
for(int i=0;i<n;i++){
cur=min(cur+cardPoints[i],cardPoints[i]);//意思是,是这个以第i+1个元素为结尾的子数组小,还是让这个第i-1个元素另起炉灶,成为新的子数组的开头
mn=min(cur,mn);//从全局的角度,一直选出最小的子数组
}
return s-mn;
}
};
如果将min换成max,可以求最大子数组,同样可解
这道题原题除了灵神的两种解法之外,还有另外一种解法,因为只能拿首部和尾部的牌,所以我们其实可以把这个数组给他变成一个环
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int s=0;
int cnt=0;
int ans=0;
for(int i=cardPoints.size()-k;i<cardPoints.size()+k;i++){
s+=cardPoints[i%cardPoints.size()];
cnt++;
if(cnt<k)continue;
ans=max(ans,s);
s-=cardPoints[(i-k+1)%cardPoints.size()];
cnt--;
}
return ans;
}
};
写完啦,希望对你有帮助~

浙公网安备 33010602011771号