
本文介绍一种时间复杂度为 o(k) 的算法,用于判断给定整数列表是否构成模 n 环形序列(1→2→…→n→1)中的严格连续子序列,要求元素唯一、顺序正确且无缝衔接(含跨 n→1 边界情况)。
本文介绍一种时间复杂度为 o(k) 的算法,用于判断给定整数列表是否构成模 n 环形序列(1→2→…→n→1)中的严格连续子序列,要求元素唯一、顺序正确且无缝衔接(含跨 n→1 边界情况)。
在处理环形编号系统(如钟表刻度、棋盘坐标、循环缓冲区索引)时,常需验证一组整数是否代表环上一段严格连续、方向一致、无重复的区间。例如,当 n = 36(模拟一圈36个刻度),[35, 36, 1] 和 [36, 1, 2] 应判定为合法连续序列,而 [1, 3, 4] 或 [3, 2, 1] 则不符合——前者跳过了 2,后者方向错误。
核心思路是:逐元素验证后继关系是否符合环形递增规则。对任意相邻两数 prev 和 curr,仅当满足以下其一,才视为合法过渡:
- curr == prev + 1(常规递增);
- prev == n 且 curr == 1(环形回绕)。
该方法避免了字符串拼接、排序或集合运算,空间复杂度 O(1),时间复杂度 O(k)(k 为子集长度),且天然保证元素唯一性与顺序性(因仅检查相邻关系,若输入含重复值,必在某次比较中因不满足递增条件而返回 False)。
以下是可直接复用的实现:
class ConsecutiveChecker:
def __init__(self, n):
self.n = n
def __call__(self, seq):
if not seq:
return True # 空序列视为平凡连续
prev = seq[0]
for curr in seq[1:]:
if curr == prev + 1:
pass # 正常递增
elif prev == self.n and curr == 1:
pass # 环形回绕:n → 1
else:
return False # 违反连续性
prev = curr
return True
# 使用示例
check = ConsecutiveChecker(36)
assert check([1, 2, 3]) # True
assert check([8, 9, 10]) # True
assert check([35, 36, 1]) # True
assert check([36, 1, 2]) # True
assert not check([1, 3, 4]) # False(跳过2)
assert not check([15, 17, 20]) # False(非连续)
assert not check([3, 2, 1]) # False(逆序)
assert not check([1, 2, 3, 1]) # False(重复且破坏后续递增)⚠️ 注意事项:
- 输入序列必须非空(空列表可按需调整逻辑);
- 该算法不自动校验输入值是否在 [1, n] 范围内——若业务场景允许越界输入,建议前置校验:all(1 <= x <= n for x in seq);
- 顺序敏感:[1, 2, 3] 有效,[3, 2, 1] 无效,符合“单向连续”语义;
- 重复元素会立即导致失败(如 [1, 2, 2] 中 2→2 不满足任一合法条件),无需额外去重。
此方案简洁、高效、可读性强,适用于嵌入式系统、游戏开发、调度算法等对性能与语义准确性均有要求的场景。

















