求解有序列表最小旋转次数的二分法Python代码排错
问题描述
需求:编写函数判断原始升序排列的列表经过多少次旋转可得到给定列表。
示例:列表[5, 6, 9, 0, 2, 3, 4]由有序列表[0, 2, 3, 4, 5, 6, 9]旋转3次得到,需要排查下述实现代码的错误。
原错误实现代码
def count_rotations_binary(nums): lo = 0 hi = len(nums)-1 while lo <= hi: mid = (lo+hi)//2 mid_number = nums[mid] print("lo:", lo, ", hi:", hi, ", mid:", mid, ", mid_number:", mid_number) if mid > 0 and nums[mid] < nums[mid-1] : # The middle position is the answer return mid elif nums[mid] < nums[len(nums)-1] : # Answer lies in the left half hi = mid - 1 else: # Answer lies in the right half lo = mid + 1 return 0 q = count_rotations_binary([9,10,11,1,4,6,7,8]) print(q)
代码错误点说明
- 缩进错误:核心的旋转点判断、左右搜索区间收缩逻辑全部写在了
while循环外部,循环内部仅执行mid计算、日志打印操作,没有修改lo/hi值的逻辑,会触发无限死循环,永远无法走到后续判断分支。 - 区间判断逻辑不严谨:原逻辑用
nums[mid]和列表最后一个元素比较判断区间位置,没有结合当前搜索的右边界hi做判断,在列表完全有序、旋转点在首尾位置时会出现判断错误。 - 边界场景缺失:没有处理空列表、单元素列表这类特殊输入,运行时会触发索引越界问题。
- 冗余变量:定义了
mid_number变量但全程没有使用,属于无效代码。
修正后可运行代码
def count_rotations_binary(nums): lo = 0 hi = len(nums) - 1 # 处理短列表边界场景 if len(nums) <= 1: return 0 while lo <= hi: mid = (lo + hi) // 2 mid_number = nums[mid] print("lo:", lo, ", hi:", hi, ", mid:", mid, ", mid_number:", mid_number) # 找到旋转分界点:当前元素小于前一个元素,该位置索引就是旋转次数 if mid > 0 and nums[mid] < nums[mid - 1]: return mid # 中间值大于当前搜索区间右边界值,说明旋转点在右半区间 if nums[mid] > nums[hi]: lo = mid + 1 # 否则旋转点在左半区间 else: hi = mid - 1 # 未找到分界点说明列表本身有序,旋转次数为0 return 0 q = count_rotations_binary([9,10,11,1,4,6,7,8]) print(q)
运行上述代码,针对测试用例[9,10,11,1,4,6,7,8]会正确返回旋转次数3,也可正确匹配题目给出的示例、完全有序列表、单元素列表等场景的计算结果。
内容的提问来源于stack exchange,提问作者Pranav.Vichur
相关产品推荐
相关产品推荐

