Python中替换二维数组0为1生成所有可能数组的问题排查与优化
解决4x4数组逐个替换0为1生成所有可能数组的问题
问题根源分析
你遇到的问题核心在于Python中列表是可变对象,直接append数组会导致所有元素都指向同一个内存地址。你的代码里每次p.append(arr)添加的都是原数组的引用,后续修改p[-1][i][j]=1其实是在修改同一个数组——相当于你把原数组里的0逐个改成1,而所有列表项都指向这个被反复修改的数组,最后自然全是全1的结果。
哪怕你尝试过临时拷贝,大概率用的是浅拷贝(比如arr.copy()或者list(arr)),但二维数组的浅拷贝只会复制外层列表,里面的子列表还是引用,修改子列表元素依然会影响所有拷贝。所以必须用深拷贝来创建完全独立的数组副本。
修正后的代码
我们可以用copy.deepcopy()来创建每个独立的数组副本,修改后的代码如下:
import copy def getPossibilities(arr): p = [] for i in range(4): for j in range(4): if arr[i][j] == 0: # 深拷贝原数组,创建完全独立的副本 new_arr = copy.deepcopy(arr) new_arr[i][j] = 1 p.append(new_arr) return p # 测试示例 for i in getPossibilities([[0,1,0,0],[0,0,1,0],[0,0,0,0],[0,0,0,0]]): print(i)
这段代码会正确生成14个不同的数组,每个数组只把原数组中的一个0替换成1。
更优雅高效的实现方式
如果想让代码更简洁高效,可以尝试两种优化思路:
方式1:手动构建新数组(替代深拷贝)
深拷贝对于4x4的小数组影响不大,但如果数组规模变大,手动逐行复制构建新数组会更高效——因为不需要递归复制所有层级:
def getPossibilities(arr): p = [] for i in range(4): for j in range(4): if arr[i][j] == 0: new_arr = [] for row_idx, row in enumerate(arr): if row_idx == i: # 复制当前行并修改目标位置 new_row = row.copy() new_row[j] = 1 new_arr.append(new_row) else: # 直接复制其他行(浅拷贝足够,因为不会修改这些行的元素) new_arr.append(row.copy()) p.append(new_arr) return p
方式2:列表推导式紧凑写法
如果追求代码简洁,可以先收集所有0的坐标,再用列表推导式生成结果:
import copy def getPossibilities(arr): # 先收集所有0的坐标 zero_positions = [(i,j) for i in range(4) for j in range(4) if arr[i][j] == 0] # 对每个坐标生成修改后的数组 return [ copy.deepcopy(arr)[:i] + [row[:j] + [1] + row[j+1:] for row in arr[i:i+1]] + copy.deepcopy(arr)[i+1:] for i,j in zero_positions ]
验证结果
运行上述修正后的代码,输入示例数组会得到14个不同的数组,每个数组恰好有一个0被替换为1,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Jahan
相关产品推荐
相关产品推荐

