leetcode combination-sum題集

這次對以上組合問題進行總結。題的主旨是對一個數組找到所有和爲target的組合形式。題目要求不一,下面一一介紹。

39. 組合總和

數組無重複,每個數字可以被無限次使用,要求返回所有可能的情況(順序不一樣視作一種)。用dfs。

思路:

  • 先排序,然後進行遍歷。
  • 和超過target返回。
  • target減到0時把數組加進去。
  • 注意去重,比如[1,2]和[2,1]設置加入數必須比之前所有加入的大。
class Solution(object):
    def __init__(self):
        self.res = []

    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        self.res = []
        candidates.sort()
        self.dfs(candidates, target, [])
        return self.res
    def dfs(self, candidates, val, temp):
        if 0 == val:
            self.res.append(temp)
            return
        if val < 0:
            return
        for i in range(len(candidates)):
            if candidates[i] > val: return
            if len(temp) > 0 and candidates[i] < temp[-1]:
                continue
            self.dfs(candidates, val - candidates[i], temp + [candidates[i]])
        return

40. 組合總和 II

數組有重複,每個數字只能被使用一次,要求返回所有可能的情況(順序不一樣視作一種)。用dfs。

思路:

  • 先排序,然後進行遍歷。
  • 和超過target返回,target減到0時把數組加進去。
  • 注意去重,比如[1,2]和[2,1]設置加入數必須比之前所有加入的大。
  • 此外,因爲有重複,所以每次額外傳一個參數,表示上一個用到的索引,在這個索引之前(包括這個)都不再進行遍歷。
class Solution(object):
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        res = []
        candidates.sort()
        #print candidates
        def dfs(val, path, lastind):
            if val == 0:# and path not in res:
                res.append(path)
                return
            last = None
            for i in range(len(candidates)):
                if len(path) > 0 and (candidates[i] < path[-1] or candidates[i] == path[-1] and i <= lastind): #改動
                    continue
                if candidates[i] > val:break
                if candidates[i] == last:#改動
                    continue
                dfs(val - candidates[i], path + [candidates[i]], i)
                last = candidates[i]
            return
        dfs(target, [], -1)
        return res

216. 組合總和 III

數組被指定爲range(1,10),但是要求返回到數組長度都爲指定長度k。要求返回所有可能的情況(順序不一樣視作一種)。用dfs。

思路:

  • 不需要排序,進行遍歷。
  • 和超過target返回。
  • target減到0且長度等於k時把數組加進去。
  • 注意去重,比如[1,2]和[2,1]設置加入數必須比之前所有加入的大。
class Solution(object):
    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """
        nums = range(1, 10)
        res = []
        def dfs(val, path, c):
            if len(path) == c:
                if val == 0:
                    res.append(path)
                return
            for i in range(len(nums)):
                if len(path) > 0 and nums[i] <= path[-1]:
                    continue
                if nums[i] > val:
                    return
                dfs(val - nums[i], path + [nums[i]], c)
            return
        dfs(n, [], k)
        return res

377. 組合總和 Ⅳ

數組無重複,每個數字可以被無限次使用,要求返回所有可能的情況(順序不一樣視作不同)的數量。用dfs。

思路:

  • 順序不同視爲不同結果,比如[1,1,2],[1,2,1],[2,1,1]爲三種不同的情況。
  • 因爲題只要求返回數量,計數型一般是用遞推來做。因爲dfs需要更多的複雜度。
  • 觀察發現遞推關係爲dp[i] += dp[i - num] for num in nums,即每個數而言,都可以拆分成數組中的一個數和之前dp的另一個數,比如[1,2,4],target=4的情況,dp[4]就可以拆分爲1和dp[3]的組合,2和dp[2]的組合,4和dp[0]的組合。
  • 這裏需要注意dp[0]=1表示空集和數本身的組合,只有一種情況。
class Solution(object):
    def combinationSum4(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        dp = [1]
        nums.sort()
        for i in range(1, target + 1):
            temp = 0
            for j in range(len(nums)):
                if nums[j] > i:
                    break
                temp += dp[i - nums[j]]
            dp.append(temp)
            #print dp
        return dp[-1]

總結

求數量一般按照遞推思想來做,而求所有可能情況一般是dfs。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章