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项目实战-tomcat-SpringMVC-基本用法01-day25
目录 1. maven创建 war项目 2. SpringMVC 1. maven创建 war项目 什么是jar项目 什么是war项目? jar项目: 由main方法来开始的 直接依赖JVM就能编译运 ...
- TOEFL | 202307 改革 · 新版题型总结
目录 Listening(36min) Reading(35min) Speaking(16min) Writing(29min) Listening(36min) 2 conversation,3 ...
- maven总结二: 常用标签及属性
本文为博主原创,未经允许不得转载 目录: 1. maven 依赖属性:groupId.artifactId.version 2.插件执行: execution,id ,phase,goals,con ...
- C++数据结构(树)
树是一种递归定义的数据结构,如果树中节点的各子树从左到右是有次序的,不能互换,则称该树为有序树,否则叫无序树. 关于树的节点: 节点拥有的子树的个数叫做节点的度 如果度为0,那么该节点叫做叶节点或终端 ...
- Cortex-M3 MCU的技术特点
1.Cortex-M3 MCU的技术特点 MCU简单来说就是一个可编程的中央处理器(CPU)加上一些必要的外设.不管是中央处理器还是整个MCU都是复杂的时序数字电路,根据程序或者指令来完成特定的任务. ...
- Linux系统下安装JDK8和Maven3.8.5
一.下载JDK8Linux版本 官网下载太慢了,小编这里为大家下载好了: 链接:百度网盘地址 提取码:ov24 二.下载Maven maven3.8.5下载链接 三.使用xftp上传到linux上 四 ...
- [转帖]Nginx 安全优化
目录 前言 1.使用 SSL/TLS 证书 2.使用安全密钥交换机制 3.禁用旧的 SSL/TLS 协议 4.禁用 SSL/TLS 弱密码套件 5.禁用不需要的 HTTP 方法 6.防止缓冲区溢出攻击 ...
- [转帖]《Linux性能优化实战》笔记(五)—— 不可中断进程与僵尸进程
一. 进程状态 1. 状态含义 从 ps或者 top 命令的输出中,可以看到处于不同状态的进程 R:Running 或 Runnable,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行 D ...
- [转帖]关于虚拟化中cpu的指令集SSE 4.2的不支持
背景: 局域网中有两台服务器proxmox进行了虚拟化,跑一些测试应用.今天正好想要安装一下clickhouse跑一下.安装前准备: 测试服务器是否支持sse 4.2指令集-如下 [root@slav ...
- [转帖][大数据]ETL之增量数据抽取(CDC)
https://www.cnblogs.com/johnnyzen/p/12781942.html 目录 1 CDC 概念 1.1 定义 1.2 需求背景 1.3 考察指标 2 CDC 常见解决方案 ...