
本文介绍如何高效判断一个由 1 到 n 的整数组成的子列表是否构成严格递增的连续序列(支持循环衔接,即 n 后接 1),并确保元素唯一、顺序正确、无跳变或逆序。
本文介绍如何高效判断一个由 1 到 n 的整数组成的子列表是否构成严格递增的连续序列(支持循环衔接,即 n 后接 1),并确保元素唯一、顺序正确、无跳变或逆序。
在处理环形编号系统(如钟表刻度、棋盘坐标、模运算索引等)时,常需验证一组整数是否构成“循环连续序列”——即它们在 1→2→…→n→1 的环上是相邻且有序的。关键约束包括:
- 所有元素必须在 [1, n] 范围内;
- 元素必须唯一且严格按环形递增顺序排列(不允许降序、重复或跳跃);
- 允许跨边界连续,例如当 n=36 时,[35, 36, 1] 和 [36, 1, 2] 均合法。
以下是一个简洁、高效、可复用的实现方案:
class IsConsecutiveCyclic:
def __init__(self, n):
"""初始化环形范围上限 n(所有数字应在 1..n 内)"""
self.n = n
def __call__(self, seq):
"""检查序列是否为环形连续递增序列"""
if not seq:
return False
# 验证所有元素在有效范围内且无重复
if not all(1 <= x <= self.n for x in seq):
return False
if len(seq) != len(set(seq)):
return False
prev = seq[0]
for curr in seq[1:]:
# 正常递增:prev+1 == curr
# 或环形衔接:prev == n 且 curr == 1
if curr == prev + 1 or (prev == self.n and curr == 1):
prev = curr
else:
return False
return True
# 使用示例(n = 36)
foo = IsConsecutiveCyclic(36)
print(foo([1, 2, 3])) # True
print(foo([8, 9, 10])) # True
print(foo([35, 36, 1])) # True
print(foo([36, 1, 2])) # True
print(foo([1, 3, 4])) # False(跳过 2)
print(foo([15, 17, 20])) # False(多处跳跃)
print(foo([3, 2, 1])) # False(递减)
print(foo([1, 2, 3, 1])) # False(重复 1)✅ 核心逻辑说明:
- 每次仅校验当前元素 curr 是否紧随前一元素 prev 在环上——即满足 curr == prev + 1 或 prev == n and curr == 1;
- 预检确保输入合法(范围合规、无重复),避免后续逻辑误判;
- 时间复杂度 O(k),k 为子列表长度;空间复杂度 O(k)(用于去重检查,可优化为 O(1) 若允许修改输入或信任输入唯一性)。
⚠️ 注意事项:
- 该方法不排序输入,严格依赖原始顺序——[2, 3, 4] 为真,[4, 2, 3] 为假;
- 若需支持任意顺序下的“是否可重排为循环连续”,则需额外排序与模差分判断,但不符合本题“顺序敏感”的语义;
- 对空列表返回 False,单元素列表恒为 True(长度为 1 的序列天然满足连续性)。
此实现摒弃了字符串拼接等低效方式,以清晰的数学逻辑直击问题本质,兼顾可读性、健壮性与性能,适用于竞赛编程、配置校验及嵌入式环形缓冲区验证等场景。

















