LeetCode 組合總和 Ⅳ

給定一個由正整數組成且不存在重複數字的數組,找出和爲給定目標正整數的組合的個數。

示例:

nums = [1, 2, 3]
target = 4

所有可能的組合爲:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

請注意,順序不同的序列被視作不同的組合。

因此輸出爲 7。

進階:
如果給定的數組中含有負數會怎麼樣?
問題會產生什麼變化?
我們需要在題目中添加什麼限制來允許負數的出現?

思考:

首先考慮遞歸關係。怎樣的組合的target與那些比小的數的組合的target

 

所以我們知道這target是數組中數字的總和。想象一下,我們只需要一個數字來達到目標​​,這個數字可以是陣列中的任何一個,對嗎?所以#的組合targetcomb[target] = sum(comb[target - nums[i]]), where 0 <= i < nums.length, and target >= nums[i]

 

在給出的示例中,我們實際上可以找到4個組合的#與3(4 - 1),2(4 - 2)和1(4 - 3)的組合。結果,comb[4] = comb[4-1] + comb[4-2] + comb[4-3] = comb[3] + comb[2] + comb[1]

 

然後考慮基本情況。因爲如果目標是0,只有一種方法可以獲得零,即使用0,我們可以設置comb[0] = 1

 

編輯:問題是目標是一個正整數,讓我覺得它不清楚以上述方式。由於target == 0只在前一次調用中發生了target = nums [i],我們知道這是這種情況下唯一的組合,所以我們返回1。

 

現在我們可以提出至少一個遞歸解決方案。

 

public int combinationSum4(int[] nums, int target) {
    if (target == 0) {
        return 1;
    }
    int res = 0;
    for (int i = 0; i < nums.length; i++) {
        if (target >= nums[i]) {
            res += combinationSum4(nums, target - nums[i]);
        }
    }
    return res;
}

 

現在對於DP解決方案,我們只需要找出存儲中間結果的方法,以避免多次計算相同的組合和。我們可以使用數組來保存這些結果,並在計算之前檢查是否已有結果。我們可以用-1填充數組以指示結果尚未計算。0不是一個好的選擇,因爲它意味着目標沒有組合總和。

 

private int[] dp;

public int combinationSum4(int[] nums, int target) {
    dp = new int[target + 1];
    Arrays.fill(dp, -1);
    dp[0] = 1;
    return helper(nums, target);
}

private int helper(int[] nums, int target) {
    if (dp[target] != -1) {
        return dp[target];
    }
    int res = 0;
    for (int i = 0; i < nums.length; i++) {
        if (target >= nums[i]) {
            res += helper(nums, target - nums[i]);
        }
    }
    dp[target] = res;
    return res;
}

 

編輯:以上解決方案是自上而下的。自下而上的怎麼樣?

 

public int combinationSum4(int[] nums, int target) {
    int[] comb = new int[target + 1];
    comb[0] = 1;
    for (int i = 1; i < comb.length; i++) {
        for (int j = 0; j < nums.length; j++) {
            if (i - nums[j] >= 0) {
                comb[i] += comb[i - nums[j]];
            }
        }
    }
    return comb[target];
}

 

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