以下为力扣官方题解,以及本人代码
题目
几张卡牌排成一行,每张卡牌都有一个对应的点数。点数由整数数组 c a r d P o i n t s cardPoints cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k k k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 c a r d P o i n t s cardPoints cardPoints 和整数 k k k,请你返回可以获得的最大点数。
示例1
输入: c a r d P o i n t s = [ 1 , 2 , 3 , 4 , 5 , 6 , 1 ] , k = 3 cardPoints = [1,2,3,4,5,6,1], k = 3 cardPoints=[1,2,3,4,5,6,1],k=3
输出: 12 12 12
解释:第一次行动,不管拿哪张牌,你的点数总是 1 1 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 1 + 6 + 5 = 12 1+6+5=12 。
示例2
输入: c a r d P o i n t s = [ 2 , 2 , 2 ] , k = 2 cardPoints = [2,2,2], k = 2 cardPoints=[2,2,2],k=2
输出: 4 4 4
解释:无论你拿起哪两张卡牌,可获得的点数总是 4 4 4。
示例3
输入: c a r d P o i n t s = [ 9 , 7 , 7 , 9 , 7 , 7 , 9 ] , k = 7 cardPoints = [9,7,7,9,7,7,9], k = 7 cardPoints=[9,7,7,9,7,7,9],k=7
输出: 55 55 55
解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。
示例4
输入: c a r d P o i n t s = [ 1 , 1000 , 1 ] , k = 1 cardPoints = [1,1000,1], k = 1 cardPoints=[1,1000,1],k=1
输出: 1 1 1
解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 1 1 。
示例5
输入: c a r d P o i n t s = [ 1 , 79 , 80 , 1 , 1 , 1 , 200 , 1 ] , k = 3 cardPoints = [1,79,80,1,1,1,200,1], k = 3 cardPoints=[1,79,80,1,1,1,200,1],k=3
输出: 202 202 202
提示
- 1 < = c a r d P o i n t s . l e n g t h < = 1 0 5 1 <= cardPoints.length <= 10^5 1<=cardPoints.length<=105
- 1 < = c a r d P o i n t s [ i ] < = 1 0 4 1 <= cardPoints[i] <= 10^4 1<=cardPoints[i]<=104
- 1 < = k < = c a r d P o i n t s . l e n g t h 1 <= k <= cardPoints.length 1<=k<=cardPoints.length
官方题解 滑动窗口
思路
记数组 c a r d P o i n t s cardPoints cardPoints 的长度为 nnn,由于只能从开头和末尾拿 k k k 张卡牌,所以最后剩下的必然是连续的 n − k n-k n−k 张卡牌。
我们可以通过求出剩余卡牌点数之和的最小值,来求出拿走卡牌点数之和的最大值。
算法
由于剩余卡牌是连续的,使用一个固定长度为 n − k n-k n−k 的滑动窗口对数组 c a r d P o i n t s cardPoints cardPoints 进行遍历,求出滑动窗口最小值,然后用所有卡牌的点数之和减去该最小值,即得到了拿走卡牌点数之和的最大值。
本人代码
class Solution {
public int maxScore(int[] cardPoints, int k) {
int n = cardPoints.length;
int size = n-k;
int sum = 0;
for (int i=0; i<size; i++)
sum += cardPoints[i];
int minSum = sum;
for (int i=size; i<n; i++)
{
sum = sum + cardPoints[i] - cardPoints[i-size];
minSum = Math.min(minSum, sum);
}
return Arrays.stream(cardPoints).sum()-minSum;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是 c a r d P o i n t s cardPoints cardPoints 的长度。
- 空间复杂度: O ( 1 ) O(1) O(1)。