原文链接:https://www.cnblogs.com/Time25/p/19670562.html
原题在此处

解题思路

这道题的原题大致意思可以看上面链接,有一种做法是逆向思维,也就是,只能从首部或者尾部取一个数字,那么剩下的部分肯定是连续的,假设数组长度为n,要取的数字的个数为k,也就是求数组中
n-k个连续子数组的最小值,用总和减去最小值就可以得到最终的答案

原题逆向思维解法代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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;
}
};
```cpp
###原题灵神解法代码(两种)
**(https://leetcode.cn/problems/maximum-points-you-can-obtain-from-cards/solutions/2551432/liang-chong-fang-fa-ni-xiang-si-wei-zhen-e3gb/)**
##思考题解法
同理,思考题我们也可以这样做,就是求这个数组,这整个数组的最小字段和,后来了解,这种做法其实有一个专有的名字叫做**Kadane算法**
```cpp
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,可以求最大子数组,同样可解

这道题原题除了灵神的两种解法之外,还有另外一种解法,因为只能拿首部和尾部的牌,所以我们其实可以把这个数组给他变成一个环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
};

写完啦,希望对你有帮助~

// TRAINING LOG · 第 12 / 76 篇训练记录 · 成文于 2026.03.04 · 深夜 23:58