Python数组为何无法正常执行原地交换 循环排序异常排查
异常产生原因
核心问题出在交换语句的求值顺序不符合预期,和选择if还是while没有本质关系,两个异常都是同一个根因导致的:
- Python的多元赋值规则是:先完整计算等号右侧所有表达式的结果,再按照从左到右的顺序给等号左侧的变量依次赋值。
- 你写的交换语句
row[i], row[row[i]] = row[row[i]], row[i],在给左侧第二个赋值目标row[row[i]]计算索引时,row[i]已经被第一步赋值修改过了,不再是交换前的原始值,直接导致交换逻辑失效。
为什么用if时返回原数组
拿测试用例[0,2,1,3]的执行过程拆解:
- 遍历到i=0时,row[0]=0,符合位置要求,不触发交换
- 遍历到i=1时,row[1]=2,和索引1不相等,触发交换:
- 先算等号右侧:
row[row[i]]是row[2]=1,row[i]是row[1]=2,右侧元组为(1,2) - 先给左侧第一个变量
row[i]也就是row[1]赋值1,此时数组变成[0,1,1,3] - 再给左侧第二个变量
row[row[i]]赋值,这时候取row[i]已经是刚改完的1,等价于给row[1]赋值2,数组直接变回[0,2,1,3],等于这次交换完全没生效
- 先算等号右侧:
- 后续遍历i=2、i=3时,要么交换同样失效,要么值本身匹配,最终返回原数组。
为什么换成while会触发无限循环
循环排序的正确逻辑确实是在每个索引位置持续交换,直到当前位置的值和索引匹配,也就是需要用while循环而非单次if判断。但因为交换语句永远没法把正确的值放到当前i的位置,row[i] != i的条件永远成立,循环永远不会退出,就触发了无限循环。
修复方式
交换时提前把当前值对应的正确索引存为独立变量,避免赋值过程中数组变动导致索引计算错误,参考正确实现:
def cyclic_sort(row): i = 0 while i < len(row): correct_pos = row[i] # 提前存好正确位置,不受后续赋值影响 if row[i] != row[correct_pos]: row[i], row[correct_pos] = row[correct_pos], row[i] else: i += 1 return row
测试执行cyclic_sort([0,2,1,3])会得到正确结果[0,1,2,3]。
内容的提问来源于stack exchange,提问作者softandwet
相关产品推荐
相关产品推荐

