题目传送门

题目描述

几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组

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:

输入:nums = [2,3,5,9], k = 2

输出:5

解释:

小偷窃取至少 2 间房屋,共有 3 种方式:

- 窃取下标 0 和 2 处的房屋,窃取能力为 max(nums[0], nums[2]) = 5 。

- 窃取下标 0 和 3 处的房屋,窃取能力为 max(nums[0], nums[3]) = 9 。

- 窃取下标 1 和 3 处的房屋,窃取能力为 max(nums[1], nums[3]) = 9 。

因此,返回 min(5, 9, 9) = 5 。

示例 2:

输入:cardPoints = [2,2,2], k = 2

输出:4

解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。

示例 3:

输入:cardPoints = [9,7,7,9,7,7,9], k = 7

输出:55

解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。

解题思路

逆向思维: 拿走

k

k

k 张,剩下

n

k

n - k

n−k 张(这里

n

n

n 是

c

a

r

d

P

o

i

n

t

s

cardPoints

cardPoints 的长度)。

由于拿走的点数和 + 剩下的点数和 = 所有点数和,所以为了最大化拿走的点数和,也就是要最小化剩下的点数和。

由于只能从开头或末尾拿牌,所以最后剩下的牌必然是连续的。因此,可以使用一个固定长度为

n

k

n - k

n−k 的滑动窗口对数组

c

a

r

d

P

o

i

n

t

s

cardPoints

cardPoints 进行遍历,求出滑动窗口最小值,然后用所有卡牌的点数之和减去该最小值,即得到了拿走卡牌点数之和的最大值。

至此,问题变成:

计算长为

n

k

n−k

n−k 的连续子数组和的最小值。

因此这题就转化为了窗口大小为

n

k

n - k

n−k 的滑动窗口题了。

AC代码:

class Solution {

public:

int maxScore(vector& cardPoints, int k) {

int left = 0, right = cardPoints.size() - k, n = cardPoints.size();

int res = accumulate(cardPoints.begin(), cardPoints.begin() + n - k, 0);

int ans = res;

while(right < n) {

res += cardPoints[right++];

res -= cardPoints[left++];

ans = min(ans, res);

}

return accumulate(cardPoints.begin(), cardPoints.end(), 0) - ans;

}

};

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: