JS LeetCode 1423. 可获得的最大点数简单题解
壹 ❀ 引
最近也是浮躁的很,一篇redux的文章写了三千多字才算写了一半...写的泪目了。还是刷刷算法静下心,顺带记录下算法做题过程吧。今天的题来自LeetCode每日打卡,题目出自LeetCode1423. 可获得的最大点数,都说二月是滑动窗口月,最近做的题确实都跟滑动窗口有关....题目描述如下:
几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。
示例 1: 输入:cardPoints = [1,2,3,4,5,6,1], k = 3
输出:12
解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。
示例 2: 输入:cardPoints = [2,2,2], k = 2
输出:4
解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。
示例 3: 输入:cardPoints = [9,7,7,9,7,7,9], k = 7
输出:55
解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。
示例 4: 输入:cardPoints = [1,1000,1], k = 1
输出:1
解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 。
示例 5: 输入:cardPoints = [1,79,80,1,1,1,200,1], k = 3
输出:202
提示:
1 <= cardPoints.length <= 10^5
1 <= cardPoints[i] <= 10^4
1 <= k <= cardPoints.length
贰 ❀ 简单的题解
贰 ❀ 壹 题目分析
先简单解释下题目,给定一个由数字组成的数组,你有k次机会,每次只能从左边或者右边开头取一个数字(注意,取的过程是连续的过程),目的是取k次之后得到的数字综合最大。
我们用图示来解释例子1,这个过程可以理解是上帝视角,因为我们知道怎么选数字和最大:

(黄色为比较过程中的数字,绿色是比较完成已确定的数)
第一次选择,因为只能从左边或者右边往中间选,这两个数字都是1,但是你第二次选择只能紧挨着你上一次选择的数,上帝视角我们很明显得选择最右边的1。
第二次选择,这一次是最左边的1与倒数第二个数字6比较,很明显6更大,我们选择了6。
第三次选择,仍然是最左边的1与倒数第三个数字5比较,很明5更大,于是我们选择了5。
因为k为3,我们得到了最大和的三个数[1,6,5],和为12。
贰 ❀ 贰 想法一
我一开始的想法是用双指针,比如l为0,r为数组length-1。这样就表示了最左边与最右边的两个数,然后开始第一次比较,选择更大的数。
如果l更大,那么就让l++,因为数字得紧挨着选择,让l++的数字继续与r比较。如果r更大,自然让r--,继续与l这边的数字比较。
但是,例子一直接否定了我这个想法,比如一开始r和l的两个数字都是1,我们是站在上帝视角知道倒数第二个数更大,所以第一次应该选择最右边的1,但站在程序的角度这就很麻烦了,如果第一次比较两个数字相等,我还得考虑两个数字紧挨着的第二个数谁大谁小,如果这次又相等了?难道继续比较紧挨着的第三个数?那要考虑的就没玩没了了,因此直接否决了这个方案。
贰 ❀ 叁 想法二
因为k个数字总是连续的,我们假设有个窗口一开始包含了k个数字,它们的和就是最大。比如我们可以假设一开始就是最左边的k个数字的和最大,之后滑动窗口,让窗口不停左滑动(每次滑动一个数字),并比较当前k个数字的和与上次的和谁更大。
我们用图表示这个过程(红框代表这个滑动窗口):

一开始,我们选中了最左边的k个数字,并求它们的和sum,假设这个和就是最大的。
开始滑动窗口,此时的和应该是减去左边第三个数字并加上最右边第一个数字,这个和和sum比较,看谁更大,记录下来。
继续滑动操作,因为我们一共只能取k个数字,所以滑动过程也只会执行k次。
如果你之前没有思路,看到了这里可以根据此思路自己尝试一下。
下面就是我的实现逻辑:
/**
* @param {number[]} cardPoints
* @param {number} k
* @return {number}
*/
var maxScore = function (cardPoints, k) {
// 想法一:我的想法是双指针,一开始就比较l和r谁大,更大的就缩进,继续比较
// 否定想法一,如果一开始l和r相等,不知道到底缩进谁了
// 想法二:一开始全拿一边的,然后不断减去左边的,加上右边的,看看最大能多大
// 最极端的就是右边k个相加最大,一直把左边k个都减完了
// 先求左边三个的和
let sum = 0;
let ans;
for (let i = 0; i < k; i++) {
sum += cardPoints[i];
};
// 开始执行减去左边的,需要注意的是,左边是从右往左减,右边是从右往左加,按照这个顺序
// 一共需要操作k次
let n = cardPoints.length - 1;
// sum等会要不断减少,会变化,所以要有个比较和大小的参照,我们也假设sum此时就是最大
ans = sum;
while (k > 0) {
sum = sum - cardPoints[k - 1] + cardPoints[n];
// ans用于记录每次计算后更大的那个数字
ans = Math.max(sum, ans);
k--;
n--;
}
return ans;
};
贰 ❀ 肆 想法三
当然,我看了下还有其它思路,比如我们要求k的和最大,就可以假设length-k个数字的和最小,同样开始滑动找到最小和的组合,那么剩下的k的数字必然和最大(max(k) = sum - min(length-k))。这里我就直接贴下官方的代码了:
var maxScore = function(cardPoints, k) {
const n = cardPoints.length;
// 滑动窗口大小为 n-k
const windowSize = n - k;
// 选前 n-k 个作为初始值
let sum = 0;
for (let i = 0; i < windowSize; ++i) {
sum += cardPoints[i];
}
let minSum = sum;
for (let i = windowSize; i < n; ++i) {
// 滑动窗口每向右移动一格,增加从右侧进入窗口的元素值,并减少从左侧离开窗口的元素值
sum += cardPoints[i] - cardPoints[i - windowSize];
minSum = Math.min(minSum, sum);
}
let totalSum = 0;
for (let i = 0; i < n; i++) {
totalSum += cardPoints[i];
}
return totalSum - minSum;
};
那么到这里本文结束。
JS LeetCode 1423. 可获得的最大点数简单题解的更多相关文章
- C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...
- C#版 - Leetcode 201. 数字范围按位与(bitwise AND) - 题解
C#版 - Leetcode 201. 数字范围按位与(bitwise AND) - 题解 在线提交: https://leetcode.com/problems/bitwise-and-of-num ...
- (转)用JS获取地址栏参数的方法(超级简单)
转自http://www.cnblogs.com/fishtreeyu/archive/2011/02/27/1966178.html 用JS获取地址栏参数的方法(超级简单) 方法一:采用正则表达式获 ...
- 用js实现菜单的下拉列表,实用又简单
下拉列表本可以用<select>配合<option>来写,方便得很.但是在前端中,好用的东西都有兼容,为了避免出现兼容性的问题,下拉列表用js写再合适不行了. <body ...
- js中的splice方法和slice方法简单总结
slice:是截取用的 splice:是做删除 插入 替换用的 slice(start,end): 参数: start:开始位置的索引 end:结束位置的索引(但不包含该索引位置的元素) 例如: va ...
- 前端(十七)—— jQuery基础:jQuery的基本使用、JQ功能概括、JS对象与JQ对象转换、Ajax简单应用、轮播图
jQuery的基本使用.JQ功能概括.JS对象与JQ对象转换.Ajax简单应用.轮播图 一.认识jQuery 1.什么是jQuery jQuery是对原生JavaScript二次封装的工具函数集合 j ...
- 【LeetCode】1423. 可获得的最大点数 Maximum Points You Can Obtain from Cards (Python)
作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 本文关键词:LeetCode,力扣,算法,算法题,滑动窗口,递归,前缀和,preSum,刷题群 目录 题目描述 解题思路 递归 ...
- Leetcode 149.直线上最多的点数
直线上最多的点数 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | | o ...
- Java实现 LeetCode 149 直线上最多的点数
149. 直线上最多的点数 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | | o | ...
- 力扣1423. 可获得的最大点数-C语言
题目 题目链接 几张卡牌 排成一行,每张卡牌都有一个对应的点数.点数由整数数组 cardPoints 给出. 每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌. 你的点数就是 ...
随机推荐
- Java 使用二分查找快速定位元素位置
转载请注明出处: 快速定位 一个有序数列中 某一个元素的位置: 共有三种思路: 第一种:使用 for 循环,匹配元素值 与循环变量的值是否相等,相等则循环变量时的 i 则为元素位置 第二种:使用 二分 ...
- Gradle 出现 Could not resolve gradle
Gradle 在进行 sync 的时候会出现 Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could n ...
- spring--是如何解决单例模式下循环依赖问题的
Spring 解决单例 bean 的循环依赖主要依赖于容器的三级缓存机制,以及 bean 的提前暴露.这里是它如何工作的: 三级缓存: 一级缓存(singletonObjects):存储已经经过完整生 ...
- 如何开发一套苹果cms前端模板
本文运用了苹果cms官网的模板开发教程,开发了一套苹果cms的前端模板,感兴趣的同学可以去github下载使用. 什么是模板 模板是网站的主题外观,也被称为主题或皮肤.通过使用不同的模板,网站的前台可 ...
- ffmpeg 字幕解码
原文: https://blog.csdn.net/u011283226/article/details/102241233 [写在前面] 在前一篇,我已经讲过了读取外挂字幕并显示的方法:理解过滤图并 ...
- [转帖]--build=arm-linux
今天在arm上用configure生成makefile时报错:configure: error: cannot guess build type; you must specify one 问题: 不 ...
- [转帖]【JVM】JDK命令行工具
在JDK/bin目录下我发现了许多命令行工具 这些命令有哪些作用呢,接下来我就来详细介绍一下 常用JDK命令行工具 命令名称 全称 用途 jstat JVM Statistics Monitoring ...
- 部分操作系统不支持 zip unzip 大于4G的文件.
https://www.ibm.com/mysupport/s/question/0D50z00006PD9XXCA1/bad-zipfile-offset-local-header-sig-erro ...
- 【发现一个问题】macos m2 下无法使用 x86_64-linux-musl-gcc 链接含有 avx512 指令的 c 代码
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 一开始是使用 golang 中的 cgo 来编译: env ...
- Seata分布式事务 (理论与部署相结合)
分布式事务--Seata 分布式事务 1. 本地事务与分布式事务 1.1 本地事务 本地事务,也就是传统的单机事务.在传统数据库事务中,必须要满足四个原则: 1.2 分布式事务问题 分布式事务,就是指 ...