
本文详解如何通过模拟索引跳转遍历,判断给定非负整数列表能否从索引0出发、不重复访问所有位置、最终停在值为0的元素上——即满足“完美扫描”条件。
本文详解如何通过模拟索引跳转遍历,判断给定非负整数列表能否从索引0出发、不重复访问所有位置、最终停在值为0的元素上——即满足“完美扫描”条件。
要解决“完美扫描”问题,关键在于模拟动态索引跳转过程,而非顺序遍历列表。给定列表 lst(元素均为非负整数),扫描规则如下:
- 起始位置为索引
0; - 每一步将当前索引
i更新为lst[i](即用当前元素值作为下一个索引); - 扫描持续进行,直到遇到
lst[i] == 0(成功终止),或发生越界、重复访问(失败); - “完美”定义为:恰好访问所有索引各一次,且最终停在值为
0的位置。
使用 for 循环无法自然表达这种依赖前一步结果的动态跳转逻辑,而 while 循环配合状态记录才是正解。核心要点有三:
-
维护已访问索引集合(
set)以检测环路; -
严格校验索引合法性(
0 ≤ curr_index ),防止越界; -
终止后双重验证:是否访问全部索引 + 是否停在
0上。
以下是完整、健壮的实现:
def is_perfect(lst):
"""
判断列表是否构成完美扫描路径:
- 从索引0开始,按 lst[i] 跳转;
- 不重复访问任意索引;
- 最终停在值为0的元素上,且覆盖全部索引。
"""
if not lst: # 空列表视为非完美
return False
visited = set()
curr_index = 0
while 0 <p>⚠️ 注意事项: </p>
-
索引安全性:必须在每次跳转前检查
curr_index是否在[0, len(lst))范围内,否则lst[curr_index]将抛出IndexError; -
环路检测不可省略:若未用
visited集合记录,像[2,2,3,2,0]这类含环列表会陷入无限循环; -
终止条件精准性:仅
lst[curr_index] == 0不足以判定“完美”,还需确保len(visited) == len(lst),即无遗漏、无重复; -
边界处理:空列表、单元素列表(如
[0])需单独验证——[0]返回True(起点即终点,访问1个元素,值为0)。
该算法时间复杂度为 O(n)(每个索引最多访问一次),空间复杂度为 O(n)(visited 集合最坏存储全部索引),兼具正确性与效率,是解决此类“索引链式遍历”问题的标准范式。










