LeetCode 39. 组合和 - 如何避免重复

发布于 2025-01-17 02:04:57 字数 1519 浏览 3 评论 0原文

我正在做 leetcode 39. 组合总和。

给定一个不同整数候选者数组和一个目标整数目标,返回所有唯一组合的列表 候选人 所选数字总和为 目标。您可以按任何顺序返回组合。

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

对于给定的输入,保证总和为目标的唯一组合数量少于150个组合。

约束

  • 1 <=候选人.length <= 30
  • 1 <= 候选人[i] <= 200
  • 候选的所有元素都不同
  • 1 <= 目标 <= 500

我能够编写以下代码:

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        output = []
        
        def backtrack(currNbr, comb):
            if currNbr == 0:
                output.append(comb.copy())
                return
            elif currNbr < 0:
                return
            
            for nbr in candidates:
                comb.append(nbr)
                currNbr = currNbr - nbr
                backtrack(currNbr, comb)
                comb.pop()
                currNbr = currNbr + nbr
                
        backtrack(target, comb = [])  
        
        return output
        

但是,我无法对其进行排序以避免重复。我在网上看到了一些解决方案,但它们似乎都使用索引i。谁能向我解释一下如何更改我的代码以避免重复?

I am doing leetcode 39. Combination Sum.:

Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.

The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.

It is guaranteed that the number of unique combinations that sum up to target is less than 150 combinations for the given input.

Constraints

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • All elements of candidates are distinct.
  • 1 <= target <= 500

I was able to write the following code:

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        output = []
        
        def backtrack(currNbr, comb):
            if currNbr == 0:
                output.append(comb.copy())
                return
            elif currNbr < 0:
                return
            
            for nbr in candidates:
                comb.append(nbr)
                currNbr = currNbr - nbr
                backtrack(currNbr, comb)
                comb.pop()
                currNbr = currNbr + nbr
                
        backtrack(target, comb = [])  
        
        return output
        

However, I cannot make it in sort to avoid duplicates. I have seen some solutions online but they all seem to use an index i. Can anyone please explain to me, how to change my code to avoid duplicates?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温柔嚣张 2025-01-24 02:04:58

是的,使用索引 i 是很常见的。这是因为,一旦您迭代到组合的下一个nbr,在更深的递归中,不应该从combinations中选择一个条目< em>在此处选择的之前。

您可以在没有 i 的情况下执行此操作,而是传递 combinations 的缩短副本,其中仅包含仍允许选择的条目。

有几种方法可以做到这一点。当您还想缩短列表时,应该注意正确地迭代列表。此外,pop()pop(0) 更高效。所以我选择使用 reversed 以相反的顺序迭代:

        def backtrack(candidates, currNbr, comb):   # Extra parameter
            if currNbr == 0:
                output.append(comb.copy())
                return
            elif currNbr < 0:
                return
            
            for nbr in reversed(candidates):  #  Reversed iteration 
                comb.append(nbr)
                backtrack(candidates[:], currNbr - nbr, comb)  # Pass a copy
                comb.pop()
                candidates.pop()  # The discarded element should not be used 
                
        backtrack(candidates, target, comb = [])  #  Extra argument

Yes, it is common to make use of the index i. This is because once you iterate to the next nbr of combinations, nowhere in the deeper recursion, should an entry be selected from combinations that comes before the one selected here.

You can do this without i, and instead pass a shortened copy of combinations, which will only have those entries which are still allowed to be selected.

There are several ways to do this. One should take care of correctly iterating over a list when you also want to make it shorter. Also, pop() is more efficient than pop(0). So I have opted to use reversed to iterate in reversed order:

        def backtrack(candidates, currNbr, comb):   # Extra parameter
            if currNbr == 0:
                output.append(comb.copy())
                return
            elif currNbr < 0:
                return
            
            for nbr in reversed(candidates):  #  Reversed iteration 
                comb.append(nbr)
                backtrack(candidates[:], currNbr - nbr, comb)  # Pass a copy
                comb.pop()
                candidates.pop()  # The discarded element should not be used 
                
        backtrack(candidates, target, comb = [])  #  Extra argument
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文