列表的 pop 和 [:-1] 之间的差异,以及当 s 是字符串或列表时 s[:-1] 的不同行为

  • 本文关键字:列表 字符串 之间 pop python string list
  • 更新时间 :
  • 英文 :


我最近一直在练习leetcode,刚刚做了"组合和"问题(删节,完整的陈述可以在 https://leetcode.com/problems/combination-sum/找到)。

给定一个不同整数候选数组和一个目标整数 目标,返回所有唯一候选组合的列表,其中 所选数字的总和与目标相加。您可以返回组合 任何订单。

可以从候选人中选择相同的号码,数量不限 次。如果频率至少为以下一种,则两个组合是唯一的 选择的数字是不同的。

我使用一种简单的回溯方法正确解决了这个问题,该方法构建了一个部分解决方案,然后使用以下帮助程序函数将其附加到数组和数组中(部分是一个列表)

def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
ans = []
def helper(candidates, target, partial):
if target == 0:
ans.append(partial[:])
return
if target < 0:
return
for i in range(0,len(candidates)):
partial.append(candidates[i])
helper(candidates[i:], target-candidates[i], partial)
partial.pop()

candidates.sort()
helper(candidates,target,[])
return ans

这段代码有效,我很满意。但是,如果我将最后一行更改为:

partial = partial[:-1]

该解决方案不再有效。特别是,元素不会像我想要的那样被删除,我的 ans 数组最终会得到包含大量不正确元素的解决方案。直觉上,我希望这些服务于从部分中删除最后一个元素的相同目的。

我怀疑这与我缺少的参考文献和列表切片有关。为什么当我解决电话号码的leetcode问题组合(见 https://leetcode.com/problems/letter-combinations-of-a-phone-number/)时没有这个问题,该号码要求枚举来自数字 - 字母电话映射的所有可能字符串,给定一串数字?

在这里,我使用了相同的帮助程序函数结构:

def letterCombinations(self, digits: str) -> List[str]:
ans = []
MAPPING = ('0', '1', "abc", "def", 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz')
def helper(s, partial_sol):
if len(s) == 0:
ans.append(partial_sol)
return
else:
for i in MAPPING[int(s[0])]:
partial_sol = partial_sol + i
helper(s[1:], partial_sol)
partial_sol = partial_sol[:-1]
if len(digits) == 0:
return ans
helper(digits, "")
return(ans)

我的解决方案是正确的。请注意,虽然我使用了 [:-1] 方法,该方法不适用于列表上的第一个问题,但在字符串上遇到了这个问题。所以我可以看到字符串与列表发生的一切都是不同的(就像在电话号码问题中一样,partial 是字符串而不是列表),我只是不知道它到底是什么,或者为什么。

简而言之,我的问题是:

  1. 为什么当我从弹出部分更改为以下时,我的组合总和解决方案不起作用:
partial = partial[:-1]
  1. 为什么该解决方案不适用于组合总和(使用列表),但适用于电话号码中的字母(使用字符串)?

你是对的,它与引用和list切片有关。

partial.pop()修改绑定到就地partiallist

partial = partial[:-1]制作了list的浅拷贝,并将partial重新绑定到新的list

这是一个重要的区别,因为重新绑定不会更改引用原始list的任何其他别名,其中包括调用者对同一list的绑定。为了使两者的行为几乎相同(pop效率更高,并且与切片不同,会在list上出错),您可以使用:

partial[:] = partial[:-1]

它将原始list的内容重新分配给浅拷贝的内容,或者,具有与pop相同(可能略好)的性能:

# Errors on empty list like pop
del partial[-1]
# Or to silently do nothing when applied to an empty list:
del partial[-1:]

直接删除元素而不返回它。

这些都不能与str一起使用,因为str是不可变的;不可能就地修改相同str的别名,您只能创建新str并重新绑定给定名称,这不适用于这种情况。一个简单的解决方案是使你的代码可以使用str将其转换为list,或者,如果str中仅出现ASCII/拉丁语-1字符,则将其编码为bytes,然后转换为bytearray这是可变的,可能允许您使用更直接地期望可变序列的代码。

最新更新