1423. 可获得的最大点数
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。
示例 1:
输入:cardPoints = [1,2,3,4,5,6,1], k = 3 输出:12 解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。
具体题目链接: 题目链接
思路:
思路:滑动窗口思路
窗口扩展时寻找可行解,窗口收缩时优化可行解
当滑动窗口可以定长时,一直维护k个长度的滑动窗口即可
当滑动窗口需要不定长时,需要通过特定条件(比如滑动窗口的总和)来判断left和right指针 到底是移动哪个
分析:
可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。获得的最大点数 可以转化成 从中间拿n-k张卡牌,获得的最小点数 也就是说滑动窗口为n-k,统计最小值,
代码:
var maxScore = function(nums, k) {
let n = nums.length;
let window = 0;
//获得第一个n-k窗口的总和
for(let i=0;i<n-k;i++) {
window += nums[i];
}
//循环获取剩下的n-k个窗口
let res = window;
// 滑动窗口的定长
let windowsize = n-k;
//滑动窗口最右边的值
let right = windowsize;
while(right<n) {
//滑动窗口最左边的值
let left = right - windowsize;
// 维护当前窗口的总和
window = window + nums[right] - nums[left];
//求最小值
res = Math.min(res, window);
right++;
}
let ans = 0;//nums各个子数组的和
for(let i=0;i<n;i++) {
ans+=nums[i];
}
return ans - res;//返回总和减中间最小值,就是两边最大值
};
总结:
这是算法系列文章「二分专题」的相关题解