壹 ❀ 引

最近也是浮躁的很,一篇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. 可获得的最大点数简单题解的更多相关文章

  1. C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  2. C#版 - Leetcode 201. 数字范围按位与(bitwise AND) - 题解

    C#版 - Leetcode 201. 数字范围按位与(bitwise AND) - 题解 在线提交: https://leetcode.com/problems/bitwise-and-of-num ...

  3. (转)用JS获取地址栏参数的方法(超级简单)

    转自http://www.cnblogs.com/fishtreeyu/archive/2011/02/27/1966178.html 用JS获取地址栏参数的方法(超级简单) 方法一:采用正则表达式获 ...

  4. 用js实现菜单的下拉列表,实用又简单

    下拉列表本可以用<select>配合<option>来写,方便得很.但是在前端中,好用的东西都有兼容,为了避免出现兼容性的问题,下拉列表用js写再合适不行了. <body ...

  5. js中的splice方法和slice方法简单总结

    slice:是截取用的 splice:是做删除 插入 替换用的 slice(start,end): 参数: start:开始位置的索引 end:结束位置的索引(但不包含该索引位置的元素) 例如: va ...

  6. 前端(十七)—— jQuery基础:jQuery的基本使用、JQ功能概括、JS对象与JQ对象转换、Ajax简单应用、轮播图

    jQuery的基本使用.JQ功能概括.JS对象与JQ对象转换.Ajax简单应用.轮播图 一.认识jQuery 1.什么是jQuery jQuery是对原生JavaScript二次封装的工具函数集合 j ...

  7. 【LeetCode】1423. 可获得的最大点数 Maximum Points You Can Obtain from Cards (Python)

    作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 本文关键词:LeetCode,力扣,算法,算法题,滑动窗口,递归,前缀和,preSum,刷题群 目录 题目描述 解题思路 递归 ...

  8. Leetcode 149.直线上最多的点数

    直线上最多的点数 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | |        o ...

  9. Java实现 LeetCode 149 直线上最多的点数

    149. 直线上最多的点数 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | | o | ...

  10. 力扣1423. 可获得的最大点数-C语言

    题目 题目链接 几张卡牌 排成一行,每张卡牌都有一个对应的点数.点数由整数数组 cardPoints 给出. 每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌. 你的点数就是 ...

随机推荐

  1. Julia编程基础

    技术背景 Julia目前来说算是一个比较冷门的编程语言,主要是因为它所针对的应用场景实在是比较有限,Julia更注重于科学计算领域的应用.而Julia最大的特点,就是官方所宣传的:拥有C的性能,且可以 ...

  2. Introduction to DFT

    服务器使用 登陆服务器:输入账号密码 打开terminal,保证至少一个terminal窗口是打开的 取消Linux操作系统的屏幕保护 设置Linux EDA工具配置 // 自定义环境变量设置 gvi ...

  3. 12-Verilog-同步FIFO设计

    同步FIFO和异步FIFO FIFO分为一个同步FIFO,一个异步FIFO,FIFO有读口和写口 读写时钟是一个,就是同步FIFO;读写时钟不是一个,异步FIFO IP核设计中,一般使用同步FIFO设 ...

  4. vscode插件 - 浏览器中自动刷新 Live Server

  5. CAP-BASE

  6. [转帖]Web技术(六):QUIC 是如何解决TCP 性能瓶颈的?

    文章目录 一.QUIC 如何解决TCP的队头阻塞问题? 1.1 TCP 为何会有队头阻塞问题 1.2 QUIC 如何解决队头阻塞问题 1.3 QUIC 没有队头阻塞的多路复用 二.QUIC 如何优化T ...

  7. [转帖]TiDB-unsafe recover(三台tikv宕机两台)

    一.背景 名称 数量 tikv 3 副本 3 1.故障: 因为某些原因,两台tikv不可连接,出现region不能访问的故障 2.几条理论: 2.1.多副本原则 存在一半以上的副本则集群访问不受影响( ...

  8. [转帖]缓存与存储的一致性策略:从 CPU 到分布式系统

    https://zhuanlan.zhihu.com/p/151745863 在计算机系统设计实践中,我们常常会遇到下图所示架构: 为了解决单个存储器读吞吐无法满足要求的问题,常常需要在存储器上面增加 ...

  9. [转帖]比快更快的 ELK 8 安装使用指南-Elasticsearch,Kibana,Logstash

    https://juejin.cn/post/7133907643386560519 携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情 Elastic 8 ...

  10. 【转帖】Ethernet 与 Infiniband的网络特性对比

    一.两者定位 以太网(Ethernet): 应用最广泛,是最成熟的网络互联技术,也是整个互联网络大厦的基石,兼容性非常好,可实现不同的系统之间的互连互通 IB(Infiniband): 领域很专,作为 ...