news 2026/9/19 12:55:28

LeetCode 2593 题解:标记所有元素后数组的分数(排序 + 访问标记模拟)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 2593 题解:标记所有元素后数组的分数(排序 + 访问标记模拟)

LeetCode 2593 题解:标记所有元素后数组的分数(排序 + 访问标记模拟)

【免费下载链接】leetcodeLeetCode Solutions: A Record of My Problem Solving Journey.( leetcode题解,记录自己的leetcode解题之路。)项目地址: https://gitcode.com/gh_mirrors/le/leetcode

本文基于仓库 problems/2593.find-score-of-an-array-after-marking-all-elements.md 的官方题解展开,结合仓库收录情况与源码细节,完整讲解这道中等难度模拟题的题意、贪心思路、Python3 实现与复杂度分析。读完本文,你将掌握"排序后按值从小到大模拟标记"的套路,并能独立处理同类"带相邻连锁效应"的数组操作题。

题目地址与仓库收录

  • 题目:2593. 标记所有元素后数组的分数(Find Score of an Array After Marking All Elements)
  • 原题地址:https://leetcode.cn/problems/find-score-of-an-array-after-marking-all-elements/
  • 仓库收录:本题解位于 problems/2593.find-score-of-an-array-after-marking-all-elements.md,并在仓库 README.md 与 SUMMARY.md 的题解目录中均有收录(README 第 445 行、SUMMARY 第 281 行),属于仓库"经典题目解析"部分的中等难度题目之一。

题目描述

给你一个数组nums,它包含若干正整数

一开始分数score = 0,请按照下面算法求出最后分数:

  1. 从数组中选择最小且没有被标记的整数。如果有相等元素,选择下标最小的一个。
  2. 将选中的整数加到score中。
  3. 标记被选中元素;如果有相邻元素,则同时标记与它相邻的两个元素(即下标i-1i+1)。
  4. 重复此过程直到数组中所有元素都被标记。

最后返回执行上述算法后的分数。

示例 1:

输入:nums = [2,1,3,4,5,2] 输出:7 解释:我们按照如下步骤标记元素: - 1 是最小未标记元素,所以标记它和相邻两个元素:[2,1,3,4,5,2] 。 - 2 是最小未标记元素,所以标记它和左边相邻元素:[2,1,3,4,5,2] 。 - 4 是仅剩唯一未标记的元素,所以我们标记它:[2,1,3,4,5,2] 。 总得分为 1 + 2 + 4 = 7 。

示例 2:

输入:nums = [2,3,5,1,3,2] 输出:5 解释:我们按照如下步骤标记元素: - 1 是最小未标记元素,所以标记它和相邻两个元素:[2,3,5,1,3,2] 。 - 2 是最小未标记元素,由于有两个 2 ,我们选择最左边的一个 2 ,也就是下标为 0 处的 2 ,以及它右边相邻的元素:[2,3,5,1,3,2] 。 - 2 是仅剩唯一未标记的元素,所以我们标记它:[2,3,5,1,3,2] 。 总得分为 1 + 2 + 2 = 5 。

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6

前置知识

  • 哈希表(用于记录每个元素的访问 / 标记状态)

思路分析:排序 + 贪心模拟

为什么可以按排序后的顺序处理?

题目要求"每次选择最小且未标记的整数"。无论标记如何扩散,被选中的元素都必然是当前未标记集合中的最小值。因此可以先把nums排序,从小到大依次取出候选值;每次取出后,如果它尚未被标记,就累加分数并标记它本身及其左右邻居;如果已被标记,则直接跳过。

这一贪心策略之所以正确,是因为:

  • 排序保证了"当前最小"这一约束始终满足;
  • 标记状态只在取元素时被写入,排序结果不受影响;
  • 每轮选中的元素一旦被标记就不会再被选中,流程与题目描述完全一致。

模拟过程推演(以示例 1 为例)

nums = [2,1,3,4,5,2],按值排序后为1, 2, 2, 3, 4, 5,依次处理:

  1. 取最小未标记值1(原下标 1):标记下标 1、0、2,分数score = 1
  2. 2:下标 0 已被标记跳过,下标 5 未被标记,选中并标记下标 5、4(下标 6 越界忽略),score = 1 + 2 = 3
  3. 3(下标 2)已被标记跳过;
  4. 4(下标 3)未标记,标记下标 3、2、4(均已标记),score = 3 + 4 = 7
  5. 5(下标 4)已被标记跳过。

最终得分为7,与题目输出一致。可以注意到:尽管存在两个值为2的元素,算法在"值相等时选择下标最小"的规则下依然只按访问状态判断,天然满足该约束。

下标偏移的妙用

原题解代码使用了enumerate(nums, 1),让下标从 1 开始计数,并配合vis = [False] * (len(nums) + 2)构造一个左右各多留一个空位的访问标记数组。这样在标记i-1i+1时:

  • i = 1(原下标 0,数组首元素)时,i-1 = 0落在额外开辟的哨兵位上,不会越界;
  • i = n(原下标 n-1,数组尾元素)时,i+1 = n+1同样落在哨兵位上。

从而避免了在每个分支里写越界判断,代码更简洁且安全。

关键点

  • 用哈希表 / 布尔数组记录每个元素的访问(标记)状态;
  • 排序后从小到大取未标记元素,命中后更新左右邻居的访问状态;
  • 访问标记数组左右各扩充一位(哨兵),简化边界处理;
  • 取元素前必须先判断是否已访问,已访问则跳过。

代码实现(Python3)

class Solution: def findScore(self, nums: List[int]) -> int: ans = 0 vis = [False] * (len(nums) + 2) # 保证下标不越界 for i, x in sorted(enumerate(nums, 1), key=lambda p: p[1]): if not vis[i]: vis[i - 1] = True vis[i + 1] = True # 标记相邻的两个元素 ans += x return ans

代码要点逐行拆解:

  • enumerate(nums, 1):为每个元素生成(下标, 值)对,下标从 1 开始,为哨兵位设计服务;
  • sorted(..., key=lambda p: p[1]):按值升序排列,保证每次取到的是"当前最小";
  • vis[i - 1] = Truevis[i + 1] = True:标记选中元素的两个邻居(选中元素本身因后续循环中被排序固定、且不会再被选中,无需单独置位也能保证正确性——当然若值相等,已选中的下标在后续遇到时也会因vis[i]已被邻居标记而跳过);
  • if not vis[i]:核心判断,保证不重复累加已被标记的索引;
  • ans += x:将选中值累加入总分。

关于最后一点值得展开:被选中的元素自身并不需要在选中当轮显式标记,因为排序后每个(下标, 值)对只会被遍历一次;当后续轮次再次遇到该下标时,它早已被某次操作标记(可能是作为被选中的元素被自己或邻居的标记覆盖),vis[i]True自然被跳过。从代码逻辑可以推断,即使两个相同值相邻,先被选中的那个也会把另一个标记掉,这与"值相等选择下标最小"的规则完全吻合。

复杂度分析

n为数组长度:

  • 时间复杂度:O(n log n)。主要开销在于对n(下标, 值)对进行排序;排序后的遍历为线性扫描,每次循环内是 O(1) 的数组访问与赋值。
  • 空间复杂度:O(n)(以本实现而言)。vis数组长度为n + 2,占 O(n) 空间;排序本身是否产生额外空间取决于内置排序算法的实现(Python 的 TimSort 为 O(n) 辅助空间)。原题解将其表述为"不确定,取决于内置的排序算法",是指排序辅助空间;若只统计显式数据结构,则vis数组严格为 O(n)。

同类题目延伸:排序 + 访问标记思想在仓库中的应用

"排序后按约束顺序处理 + 状态标记跳过"是高频套路,仓库中还有多道题目与之思想相通,可以对照学习:

  • 2007. 从双倍数组中还原原数组:同样需要对数组排序,从小到大确定元素归属,并用"已使用"状态避免重复选取;
  • 2592. 最大化数组的伟大值:与本题同属 2590 系列周赛题,同样依赖排序后贪心匹配;
  • 上述题目均收录于仓库 problems 目录,可在 README.md 的题目索引中按编号快速定位。

这类题目的共性解题模板可以总结为三步:排序确定处理顺序 → 状态数组记录占用/标记 → 顺序遍历时跳过已被处理的位置。掌握这一模板,遇到"每次选最小/最大 + 禁止重复 + 连锁影响邻居"的模拟题都能快速切入。

小结

LeetCode 2593 是一道披着模拟外衣的贪心排序题。核心在于:

  1. 用排序保证"每次取最小未标记元素";
  2. 用布尔数组记录访问状态,处理"相邻连锁标记";
  3. 通过下标偏移 + 哨兵位,让边界处理变得优雅无分支。

整体解法 O(n log n) 时间、O(n) 空间,在n <= 10^5的约束下可以轻松通过。推荐配合仓库 problems/2593.find-score-of-an-array-after-marking-all-elements.md 原文反复揣摩,并结合上述同类题目加深对该套路的理解。

【免费下载链接】leetcodeLeetCode Solutions: A Record of My Problem Solving Journey.( leetcode题解,记录自己的leetcode解题之路。)项目地址: https://gitcode.com/gh_mirrors/le/leetcode

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 12:54:21

72小时直播抢救实录:N_m3u8DL-RE 流媒体下载从0到1

72小时直播抢救实录&#xff1a;N_m3u8DL-RE 流媒体下载从0到1 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE …

作者头像 李华
网站建设 2026/9/19 12:52:32

QMK 键盘移植实战:解析 clawsome/suv 全尺寸 104 键键盘固件配置

QMK 键盘移植实战&#xff1a;解析 clawsome/suv 全尺寸 104 键键盘固件配置 【免费下载链接】qmk_firmware Open-source keyboard firmware for Atmel AVR and Arm USB families 项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware 导读 SUV 是 Clawsome…

作者头像 李华
网站建设 2026/9/19 12:51:21

HTML与CSS基础实战:从文档结构到布局动画的完整指南

1. 从一行<!doctype html>说起&#xff1a;为什么每个前端人都绕不开这套基础打开任何一个网页&#xff0c;右键查看源代码&#xff0c;第一行大概率是<!doctype html>。这行看起来像注释又像标签的东西&#xff0c;是 HTML 文档的声明&#xff0c;告诉浏览器用标准…

作者头像 李华
网站建设 2026/9/19 12:46:30

Unity离线语音合成实战:讯飞SDK接入与NPC对话系统解耦

在Unity里做NPC对话系统&#xff0c;很多人的第一反应是接在线TTS服务&#xff0c;跑通确实快&#xff0c;但一旦项目要上展会、做离线演示、或者面向网络不稳定的场景&#xff0c;在线方案立刻变成累赘。我去年做一个展厅项目时就吃过这个亏&#xff1a;现场网络时断时续&…

作者头像 李华