LeetCode 78子集问题Python代码append操作异常排查
LeetCode 78「子集」Python实现异常排查
错误复现
原实现代码如下,输入长度为1的数组(如[1])时输出符合预期,输入长度大于1的数组时,sol.append(temp[i])未正确追加当前值,反而导致sol中已存储的原有元素被意外修改:
def solution(arr): sol=[[]] temp=[[]] for num in arr: for i in range(len(temp)): temp[i].append(num) sol.append(temp[i]) temp=sol.copy() return sol
问题根因
异常由Python列表的引用机制+两个逻辑错误共同导致:
- 浅拷贝未复制嵌套子列表:
temp=sol.copy()执行的是浅拷贝,仅会创建新的顶层列表对象,列表内存储的所有子列表(即各个子集)和原sol中的子列表指向同一个内存地址。后续修改temp[i]时,sol中存储的对应子列表因为是同一个对象,会被同步修改,这就是原有元素被意外篡改的直接原因。 - 原地修改旧子集而非生成新子集:遍历到新数字时,正确逻辑应该是基于上一轮的旧子集,生成「旧子集+当前数字」的全新列表对象,但代码直接对
temp[i]调用append(num),属于原地修改已经存入结果的旧子集,根本没有生成新的子集。
输入长度为1的数组时结果看似正常,是因为第一轮循环结束后才第一次执行temp拷贝,还未触发后续轮次的引用共用问题;一旦数组长度超过1进入第二轮循环,引用篡改的问题就会直接暴露。例如输入[1,2]时,第二轮处理数字2,执行temp[0].append(2)时,sol中最初存储的空列表会被同步改成[2],直接破坏之前的计算结果。
修正后实现
核心调整为:每轮遍历新数字时,基于已有子集复制生成全新的列表对象,全程不修改已经存入结果集的子集,代码如下:
def solution(arr): sol = [[]] for num in arr: new_subsets = [] # 遍历当前已生成的所有子集 for subset in sol: # 复制原子集,拼接当前数字得到全新子集,不修改原有对象 new_sub = subset.copy() new_sub.append(num) new_subsets.append(new_sub) # 将本轮新生成的子集全部追加到结果集 sol.extend(new_subsets) return sol
也可以用列表切片subset[:]替代subset.copy(),效果完全一致,写法更简洁。
内容的提问来源于stack exchange,提问作者Rishi Preetham Karpurapu
相关产品推荐
相关产品推荐

