【算法】可获得的最大点数问题

news/2025/12/9 22:21:27/文章来源:https://www.cnblogs.com/wjw-blog/p/19327872

发现leetcode中1423题很有意思。

1、问题描述:

几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。

2、分析:

问题可以抽象为,给你一个数组,你随机从数组两端一次取一个值,取到k个,
不管有多少种取法,你要保证取到的这些数字加起来值最大。

因为第一次取数,可以先从数组左边取,也可以从右边取,接着你可以继续选择从左边取或右边取。
这样左右来回横跳取值,是十分不利于与我们统计的,我们每次取了值,下次再取数组另一端的值可能最大值就更新为和更小了,
事后你才发现决策可能是错误的。

所以我们换个思路,我们取一个值,去统计数组中剩下所有元素的和。每取走一个数,剩下的元素和一定是变得更小了。
那么原问题就可以转换为,数组两端取k个值,然后统计剩下的n-k个值,具体保留哪几个连续的n-k个数使得他们的和最小。
熟悉的感觉来了,这不就是固定长度的滑动窗口吗?

进而,我们的问题就变为遍历数组,统计数组中连续n-k个元素之和。并且我们遍历数组时不断更新这个和。
从第n-k+1个元素(下标n-k)开始,更新方法:窗口的和winSum = 原winSum + 新进窗口的元素值 - 出窗口的值。
若winSum 变小了就更新这个最小值minSum,否则继续下一个元素的遍历.
遍历完成就取得了最小值了。
之后使用原数组和 totalSum - minSum 就得到了 两端k个元素的和最大。

class Solution {func maxScore(_ cardPoints: [Int], _ k: Int) -> Int {let n = cardPoints.count;let windowSize = n - k;//总和let totalSum = cardPoints.reduce(0, +);//初始窗口和var windowSum = cardPoints[0..<windowSize].reduce(0, +);//最小和默认设置为 窗口和var minSum = windowSum;if n == k {return totalSum;}// 遍历范围 windowSize..<nfor i in windowSize..<n {//窗口向右移动一格,加上新元素,减去离开窗口的元素windowSum += cardPoints[i] - cardPoints[i - windowSize];//若windowSum更小,则更新minSumif minSum > windowSum {minSum = windowSum;}}//总和减去中间 连续 n-k 张卡最小和,即为两边取k张卡的最大和return totalSum - minSum;}
}

我们使用滑动窗口遍历了一次数组,且只是用了常量个辅助变量。
所以时间复杂度:O(n),空间复杂度:O(1)。
这道题正向思考会纠结于我们每次到底是从数组头部还是尾部取值,因为情况不唯一,我们不能确保当前的取值是使得结果是最大的。
所谓正难反易。

3、还有一种思路:

我们既然是从数组头部和尾部取k个值,那么假如从头部取i个值,必然要从尾部取k-i个值。
所以我们就可以使用前缀和,后缀和。利用此消彼长的思想,枚举所有的可能,得出最大值。
这样做有一点不好,我们要用额外的空间来存储前缀和数组和后缀和数组。这也是使用空间换时间的一种思路。
前缀和有一个特点,preSum[j + 1] - preSum[i]就得到了下标i到j 这些元素的和。
提前算好前缀和,在我们需要频繁计算某段数据的和时就无须再重复计算了。

class Solution {func maxScore(_ cardPoints: [Int], _ k: Int) -> Int {let n = cardPoints.countvar prefixSum = [Int](repeating: 0, count: k + 1)var suffixSum = [Int](repeating: 0, count: k + 1)// 计算前缀和:prefixSum[i] 表示前 i 张牌的总和for i in 1...k {prefixSum[i] = prefixSum[i - 1] + cardPoints[i - 1]}// 计算后缀和:suffixSum[i] 表示后 i 张牌的总和for i in 1...k {suffixSum[i] = suffixSum[i - 1] + cardPoints[n - i]}var maxScore = 0// 枚举所有可能的组合:前 i 张 + 后 (k-i) 张for i in 0...k {let currentScore = prefixSum[i] + suffixSum[k - i]maxScore = max(maxScore, currentScore)}return maxScore}
}

需要说明的是 prefixSum的长度是n+1,prefixSum[0] = 0,意思是数组开头取0个数。prefixSum[1]就是取第0个数+取第1个数。那么取所有数,就是prefixSum[n],共n+1个元素。依次类推
suffixSum同样,suffixSum[0]表示右边取0个元素的和,也就是我们初始化的值是0,suffixSum[1]表示从数组末尾取1个元素的和+取0个元素情况下的和,suffix[2]表示nums[n-2]+nums[n-1]的和。以此类推

空间复杂度:O(n),时间复杂度:O(k)
回顾前缀和的思路,发现我们不再关心究竟怎样取数的过程,而是考虑整体就取k个值。
前缀和和后缀和组合就可以得到了所有的情况。枚举所有情况,得到最大值即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/995647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT CMake项目中spdlog编译优化实战:从30秒到毫秒级的构建优化

前言 在CMake + Qt项目开发中,我们引入了spdlog作为日志库。起初采用直接包含头文件的方式,但发现每次构建都要额外花费30秒的时间。经过一系列排查和优化,最终将这部分时间降到了毫秒级别。本文将完整记录这个优化…

【AI】第二篇 为什么会有神经网络

根据前面的n-gram的介绍,大家都发现光靠统计次数是走不通的,我们需要一个能够脑补,举一反三的方法,而不是死板的查表机器。神经网络是--“懂得举一反三的聪明人"神经网络引入了一个划时代的的概念:词向量,它…

7-16岁少儿编程课精选推荐:从启蒙到竞赛的系统路径 - 品牌测评鉴赏家

7-16岁少儿编程课精选推荐:从启蒙到竞赛的系统路径在为7-16岁的孩子选择编程教育机构时,家长们往往面临众多选择。不同机构在课程体系、教学方式和培养方向上各有侧重。本文将基于市场口碑、课程体系完整性和家长实际…

深入解析:PostgreSQL 向量扩展插件pgvector安装和使用

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

P3385 【模板】负环 题解

P3385 【模板】负环 题解差分约束系统是什么? 差分约束系统指的是一个序列 \(x={x_1,x_2,\cdots x_m}\) 和以如下形式出现的 \(n\) 元一次不等式组。 \[\left\{\begin{matrix} x_{i_1}-x_{j_1}\le c_{k_1}\\x_{i_2}-x…

权威盘点:2025年中国智能舆情监控系统市场深度解析

随着数字社会信息生态的持续演进,舆情监控工作已发生根本性变革。传统的人工信息汇总模式,正被集多模态感知、大模型智能研判与前瞻性决策支持于一体的新一代舆情监控系统所取代。行业数据显示,2025年中国舆情监测市…

qemu安装aix7.2

最近想玩玩IBM的AIX系统,由于AIX系统只能运行在IBM的power cpu上,VMware、VirtualBox只支持X86架构,QEMU全仿真的特点可以模拟出power cpu实现系统安装。 AIX系统是IBM开发的一套UNIX操作系统,它可以在所有的IBM p…

编程小白必看!免费体验课大搜罗 - 品牌测评鉴赏家

编程小白必看!免费体验课大搜罗编程小白速进!免费体验课地图来啦 编程热,为何要先体验? 在当今数字化时代,编程已成为一门炙手可热的技能 ,掀起了全民学习的热潮。从职场人士渴望提升竞争力,到家长们为孩子规划…

前端半小时,上线一下午?我用这个平台工程思路统一了全栈部署

全栈开发拯救指南:别再让你的前端去碰 Nginx 和 Docker 了 我名义上是个全栈开发者,但最近感觉自己更像个“全栈救火队员”。 一个前端组件,我可能半小时就写完了。但为了把它上线,我可能需要花一下午的时间,去跟…

2025年国内诚信的微动开关制造厂家推荐榜单,家电微动开关/鼠标微动开关/防水微动开关/微动开关/小型微动开关微动开关制造厂家哪里有 - 品牌推荐师

在工业自动化、智能家居、新能源汽车等产业蓬勃发展的当下,微动开关作为关键的基础电子元件,其可靠性直接关系到终端产品的性能与安全。面对市场上众多的微动开关制造商,采购方与工程师们常常面临“工厂哪家靠谱”的…

ABC352D 题解

ABC352D 题解ABC352D - Description 给你一个 \(n\) 的排列 \(a\),让你选出一个长度为 \(k\) 的 \(a\) 的子序列 \(b=\left [ a_{p_1},a_{p_2},\cdots ,a_{p_k} \right ]\),使得 \(\min b_i +k-1=\max b_i\) 的同时控…

CF1407D 题解

CF1407D 题解CF1407D - Description 有 \(n\) 栋楼,每栋楼有高度 \(h_i\),对于第 \(i\) 栋楼和第 \(j\) 栋楼,如果 \((i,j)\) 满足以下三个条件中的任意一个,我们认为可以从第 \(i\) 栋楼跳到第 \(j\) 栋楼:\(i+1…

12月9号

今天进行了中国古诗词的学习。

C语言深度解剖:第一章关键字(五) - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

MySQL 筛选条件放 ON 后 vs 放 WHERE 后

ON 决定如何 "连接" 表,WHERE 决定连接后 "显示" 哪些行。 这个根本区别导致了在 LEFT JOIN / RIGHT JOIN 外连接中,条件放置位置会产生巨大影响;而在 INNER JOIN 中,效果通常 等价。今天我们…

明天不干是小狗

明天不干是小狗上一条必须干 我说真的 老己,你干吧,我求求你了

CF547B 题解

CF547B 题解CF547B - Description 给你个长度为 \(n\) 的序列 \(a\),对于每个 \(1\le k\le n\),有 \(n-k+1\) 个中所有长度为 \(k\) 的子串,你需要求出这 \(n-k+1\) 个子串的区间最小值的最大值,即下面式子的值: …

SAT 辅导哪里好?2025 年优质机构推荐(含精准选择指南) - 品牌测评鉴赏家

SAT 辅导哪里好?2025 年优质机构推荐(含精准选择指南)选择 SAT 辅导机构需结合自身基础、目标分数、学习习惯及地域便利性。以下是 2025 年最新优质机构推荐,涵盖线上线下资源,针对不同需求提供精准建议: 一、全…

10403_基于Springboot的旅游管理系统

1、项目包含 项目源码、项目文档、数据库脚本、软件工具等资料; 带你从零开始部署运行本套系统。 2、项目介绍 随着旅游业的发展,越来越多的人选择通过互联网来规划自己的旅行。在线旅游信息推荐系统就是为了帮助用户…

MMH_蓝桥杯Python_语法基础_列表与循环语句基础

1.列表 列表可以极大降低我们在处理多个元素时的复杂程度; 在 Python 中,列表(list) 是一种有序、可变、可存储多种数据类型的序列数据结构,使用中括号 [] 定义,元素之间用逗号分隔。 1.创建列表 代码展示 #包…