【Lintcode】90. k Sum II

題目地址:

https://www.lintcode.com/problem/k-sum-ii/description

給定一個長度爲nn的正整數數組,數組內數字彼此不同,再給定兩個數kktargettarget,要求在數組中找所有的kk個數的組合其和爲targettarget

思路是DFS。爲了剪枝方便,可以先排個序。剪枝的技巧在於:
1、如果枚舉時發現剩下來要枚舉的數不足以填滿kk個數了,就直接退出本層枚舉(因爲接下來的數就算全加進去,也不夠kk個),回到遞歸上一層;
2、如果發現某次已經枚舉的數已經到達了kk個,但和仍然不爲targettarget,也可以直接退出本層枚舉(因爲繼續枚舉會得到size大於kk的組合),回到遞歸上一層;
3、如果發現枚舉到一個大於targettarget的數,也可以退出本層枚舉,回到遞歸上一層(因爲接下來枚舉會得到更大的和,不會得到合法的解,所以可以直接退出)。

代碼如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    /*
     * @param A: an integer array
     * @param k: a postive integer <= length(A)
     * @param target: an integer
     * @return: A list of lists of integer
     */
    public List<List<Integer>> kSumII(int[] A, int k, int target) {
        // write your code here
        List<List<Integer>> res = new ArrayList<>();
        if (A == null || A.length == 0) {
            return res;
        }
    
        Arrays.sort(A);
        
        dfs(A, k, target, 0, new ArrayList<>(), res);
        return res;
    }
    
    private void dfs(int[] A, int k, int target, int pos, List<Integer> cur, List<List<Integer>> res) {
        if (target == 0 && cur.size() == k) {
            res.add(new ArrayList<>(cur));
            return;
        }
    	
    	// 這裏是考慮的剪枝情況2
		if (cur.size() == k) {
            return;
        }
		
		// 這裏k - cur.size() <= A.length - i考慮的是剪枝情況1
        for (int i = pos; k - cur.size() <= A.length - i; i++) {      
            if (target >= A[i]) {
                cur.add(A[i]);
                dfs(A, k, target - A[i], i + 1, cur, res);
                cur.remove(cur.size() - 1);
            } else {
            	// 這裏是考慮的剪枝情況3
                return;
            }
        }
    }
}

時間複雜度O(k(nk))O(k{n\choose k}),空間複雜度O(k)O(k)

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