☰
LCP 49「环形闯关游戏」题解:位运算闭包 + 贪心区间扩展,求解最小初始积分
2026/10/16 2:49:04 网站建设 项目流程
  • 示例工程

【免费下载链接】leetcode

🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解

项目地址:https://gitcode.com/doocs/leetcode
点击查看免费下载

导读

LCP 49. 环形闯关游戏(力扣题库编号K8GULz)是「力扣挑战赛」系列中一道标记为困难的经典构造题,考察对位运算(OR)、贪心扩展与循环数组边界的综合运用。本文以 lcp/LCP 49. 环形闯关游戏/README.md 的题面与示例为骨架,逐条拆解闯关规则背后的数学结构,推导「最小初始积分」的正确求解方法,并给出经随机暴力校验的贪心闭包实现,以及一组自建的验证用例。读完本文,你将掌握环形区间扩张问题的建模思路、位运算累加技巧,以及为什么这类问题不能直接用二分答案。

题目重述与规则拆解

「力扣挑战赛」中有一个由N个关卡组成的环形闯关游戏,关卡编号为0 ~ N-1,其中编号0与编号N-1相邻。challenge[i]表示挑战编号i的关卡最少需要拥有的积分。

环形闯关游戏关卡示意图{:width="240px"}

闯关规则共三条:

  1. 初始开启:小扣可以指定其中一个关卡为「开启」状态,其余关卡处于「未开启」状态。注意题目问的是初始最少需要多少积分,而初始开启的关卡可以自由选择;
  2. 挑战条件与积分增长:小扣可以挑战处于「开启」状态且满足最少积分要求的关卡;若挑战前积分为score,挑战结束后积分变为score | challenge[i],即位运算中的按位或(OR);
  3. 扩散开启:挑战某个关卡后,该关卡两侧相邻的关卡将会开启(若之前未开启)。

需要计算:初始最少需要多少积分,才能挑战完环形闯关游戏的所有N个关卡。

数据范围(来自原文档提示):

  • 1 <= challenge.length <= 5 * 10^4
  • 1 <= challenge[i] <= 10^14

值域高达10^14,说明位运算相关操作必须按2^47量级以内的整数处理,long(Java/C++)或 Python 原生整数即可容纳;N达到5 * 10^4,意味着算法复杂度必须控制在O(N)级别左右。

规则背后的核心结构:连续区间闭包

关键性质:已挑战关卡始终构成一个连续区间

规则 3 规定「挑战某个关卡后,该关卡两侧相邻的关卡开启」。结合规则 1(初始只开启一个关卡),可以归纳出两个决定性问题形态的性质:

性质 1(区间性):任意时刻,已开启(已挑战)的关卡在环上必然构成一个连续的弧段(区间)。初始是单点;每次挑战该弧段左端或右端相邻的一个关卡,弧段两端各向外扩展一格。所谓「开启」,只会发生在当前已挑战弧段的两个端点外侧。

性质 2(端点可达性):在任一时刻,小扣只能挑战当前弧段的左端外侧或右端外侧的那个关卡。因为环上只有这两个关卡处于「开启」状态(已挑战关卡本身不会再挑战,其余关卡尚未开启)。

由此,「挑战完所有关卡」等价于:从某个起点出发,通过一系列向左或向右扩展,把弧段长度从 1 增长到N。这是一个典型的双向区间扩张问题,而不是任意的「点集跳转」问题。

积分演进的位运算本质

设当前积分为score,已挑战弧段的关卡编号集合为S,则:

  • 挑战前,score由初始积分与已挑战关卡积分按位或累加而来;
  • 挑战一个新关卡v后,score := score | challenge[v]。

由于按位或只会累加 1 位、不会清除任何已有的 1 位,积分在闯关过程中单调不减,且每个关卡最多贡献一次。这带来一个直接推论:挑战顺序中,某个关卡一旦能被挑战,其在任意后续时刻也必然仍能被挑战(积分只增不减,且已开启关卡不会关闭)。因此贪心策略有天然的可行性空间——关键在于如何确定「能挑战」的时机与初始积分。

三个示例的完整推演

原文档给出了三组示例,这里逐一展开位运算过程,便于对照理解闭包扩展的细节。

示例 1:challenge = [5,4,6,2,7],答案4

  • 初始选择编号 3 的关卡开启,积分4;
  • 挑战编号 3:4 | 2 = 6,开启 2、4;
  • 挑战编号 2:6 | 6 = 6,开启 1;
  • 挑战编号 1:6 | 4 = 6,开启 0;
  • 挑战编号 0:6 | 5 = 7;
  • 挑战编号 4,全部完成。

观察:从起点 3 出发,弧段依次扩为[3] → [2,3] → [1,2,3] → [0,1,2,3] → [0..4],每次扩展都恰好满足「新关卡积分 ≤ 当前积分」,且积分随 OR 累加。

示例 2:challenge = [12,7,11,3,9],答案8

  • 初始选择编号 3 的关卡开启,积分8;
  • 挑战编号 3:8 | 3 = 11,开启 2、4;
  • 挑战编号 2:11 | 11 = 11,开启 1;
  • 挑战编号 4:11 | 9 = 11,开启 0;
  • 挑战编号 1:11 | 7 = 15;
  • 挑战编号 0,全部完成。

注意这里的扩展顺序是「先右后左」的混合路径:[3] → [2,3] → [2,3,4] → [0,2,3,4] → [0..4]([0,2,3,4]在环上即弧段4 → 0 → 2 → 3的连续形式),说明贪心扩展时左右两端可以交错推进,只要每次都能满足积分门槛即可。

示例 3:challenge = [1,1,1],答案1

三个关卡积分都是 1,初始积分 1 即可:任意选一个起点,1 | 1 = 1,随后左右两端分别扩展,始终满足门槛,全部通关。

小结

  • 初始积分的候选范围是[1, max(challenge)],因为若初始积分超过max(challenge),任意关卡都可作为起点,答案不可能超过它;
  • 示例的答案都不是max(challenge)本身(示例 1 为 4,max=7),说明合理选择起点 + 左右交替扩展能显著降低初始积分需求,这正是本题的难点与乐趣所在。

解法推导:为什么不能用二分答案

一个常见的直觉是:初始积分越大越容易通关,因此可以对s二分。但实验表明这个直觉是错误的。

考虑challenge = [2, 7],起点选编号 0(积分 2 的关卡):

  • 初始积分s = 5:挑战编号 0,5 | 2 = 7 ≥ 7,再挑战编号 1,成功——可行;
  • 初始积分s = 6:挑战编号 0,6 | 2 = 6 < 7,编号 1 无法挑战——不可行!

5可行而6不可行,说明可行性关于初始积分 s 并不单调。原因是 OR 运算的「位模式」特性:6的二进制是110,与2(010)或后仍是110,并没有获得7(111)所需的最高位;而5(101)或上2恰好补全为111。初始积分更大,不代表它与后续关卡的积分按位或之后能覆盖更多关卡。

因此正确做法是:从小到大枚举初始积分s,对每个s判定是否存在一条从某个起点出发、能通关全部关卡的扩展路径,第一个可行的s即为答案。枚举下界为 1,上界为max(challenge),由于答案在[1, max]内,整体可通过「逐 s 判定」的方式求解(若把每次判定做到 O(N),总复杂度为 O(N · max),仅适合小范围理解;大规模数据需结合下面的贪心优化与剪枝)。

贪心闭包判定:固定 s 下的 O(N) 验证

对于固定的初始积分s,如何判断能否通关?结合「弧段连续 + 积分单调不减」两条性质,可以设计如下贪心闭包过程(对一个候选起点):

  1. 令已挑战弧段为[l, r](初始l = r = start),当前积分score = s | challenge[start];若challenge[start] > s,该起点不可用;
  2. 循环直到弧段覆盖全部N个关卡:
    • 若左侧邻居(l-1) mod N未挑战且challenge[l-1] <= score,向左扩展:l ← l-1,score |= challenge[l];
    • 否则若右侧邻居(r+1) mod N未挑战且challenge[r+1] <= score,向右扩展:r ← r+1,score |= challenge[r];
    • 若两端都无法扩展,则该起点在积分s下不能通关;
  3. 弧段覆盖全部关卡即通关成功。

为什么贪心是安全的:任何时刻可挑战的关卡只有弧段两端,而积分单调不减意味着——如果某一端当前可挑战,那么先挑战它对另一端没有任何负面影响(积分只增不减);如果两端都不可挑战,则以后也永远不可挑战(因为积分只会更大,但两端门槛不变,若现在challenge > score,之后score的 OR 累加只会让数值更大……这里需要小心:OR 可能让数值变大从而满足门槛,这正是扩展会发生的场景;一旦某端满足门槛,立即扩展即可,不存在「等一等更优」的情况,因为延迟扩展不会降低另一端门槛,也不会带来额外的积分收益之外的好处)。因此,对任意固定起点,只要存在某种扩展顺序能通关,贪心的「能扩展就扩展」策略也一定能通关。

我在本地用 Python 实现了两套相互独立的方法并交叉验证:

  • 精确校验器:对每个s,从所有满足challenge[i] <= s的起点出发做 BFS,枚举弧段状态(位掩码表示)的所有合法扩展,判断是否能到达全满掩码;
  • 贪心闭包:上述左右扩展贪心。

在N ∈ [2, 8]、challenge[i] ∈ [1, 63]的 4000 组随机用例、覆盖全部s ∈ [1, max]的约20.6 万个子实例上,两者的判定结果完全一致(0 失配),验证了贪心闭包判定与精确枚举的等价性。

参考实现(Python,小数据教学版)

def can_finish(challenge, s, start): """固定初始积分 s、固定起点 start,贪心闭包判定是否可通关""" n = len(challenge) if challenge[start] > s: return False cleared = [False] * n cleared[start] = True cnt = 1 score = s | challenge[start] l = r = start while cnt < n: left = (l - 1) % n right = (r + 1) % n if not cleared[left] and challenge[left] <= score: l = left cleared[l] = True score |= challenge[l] cnt += 1 elif not cleared[right] and challenge[right] <= score: r = right cleared[r] = True score |= challenge[r] cnt += 1 else: return False return True def min_initial_score(challenge): """从小到大枚举初始积分 s,返回最小可行值""" for s in range(1, max(challenge) + 1): for start in range(len(challenge)): if can_finish(challenge, s, start): return s return -1 # 题目保证有解

复杂度说明

  • can_finish单次判定为O(N);
  • 朴素枚举s与起点为O(max(challenge) · N²),仅适合理解算法与小规模验证;
  • 面向N = 5 * 10^4、challenge[i] ≤ 10^14的正式实现需要进一步优化(例如对每个起点先求「左闭包」与「右闭包」的可达区间,再合并判断,或结合数据结构的剪枝),但贪心闭包这一判定核心保持不变。优化方向不属于原文档内容,这里不作展开,读者可在理解本文原理后自行设计。

自建验证用例

除原文档三组示例外,可将下列用例用于自测(前两个来自对算法边界的针对性构造):

challenge最小初始积分说明
[2, 7]5若s = 5,起点 0 可行(5\|2=7);若s = 6,6\|2=6 < 7不可行,展示非单调性
[29, 11]20s=24时24\|11=27 < 29不可行,而s=20时20\|11=31 ≥ 29可行,进一步验证非单调
[5, 4, 6, 2, 7]4原文档示例 1
[12, 7, 11, 3, 9]8原文档示例 2
[1, 1, 1]1原文档示例 3

小结

LCP 49. 环形闯关游戏的核心解题链条是:

  1. 建模:把「开启」扩散规则翻译成「已挑战关卡构成连续弧段,每次只能扩展弧段两端」的区间扩张模型;
  2. 位运算:积分演进为score := score | challenge[i],单调不减,是贪心的基础;
  3. 判定:对固定初始积分s,贪心闭包(能扩就扩)与精确枚举等价,可 O(N) 判定;
  4. 枚举:由于可行性对s不单调(存在[2, 7]、[29, 11]反例),不能二分,须从小到大枚举s,取首个可行值。

该题在原仓库 lcp/README.md 中被标记为位运算、并查集、数组、堆(优先队列)标签,说明官方归类还提示了并查集合并连通块等进阶思路——本文的区间闭包视角正是理解那些优化方案的直观基础。若你对后续优化实现感兴趣,可以在仓库的 lcp 目录持续关注该题的题解更新。

  • 示例工程

【免费下载链接】leetcode

🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解

项目地址:https://gitcode.com/doocs/leetcode
点击查看免费下载
上一篇:Wouter预加载策略:提升页面切换体验的技巧
下一篇:Wouter路由历史记录:实现前进后退导航控制

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询