【Lintcode】90. k Sum II

题目地址:

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

给定一个长度为 n n n的正整数数组,数组内数字彼此不同,再给定两个数 k k k t t t,要求在数组中找所有的 k k k个数的组合其和为 t t t

思路是DFS。为了剪枝方便,可以先排个序。剪枝的技巧在于:
1、如果枚举时发现剩下来要枚举的数不足以填满 k k k个数了,就直接退出本层枚举(因为接下来的数就算全加进去,也不够 k k k个),回到递归上一层;
2、如果发现某次已经枚举的数已经到达了 k k k个,但和仍然不为 t t t,也可以直接退出本层枚举(因为继续枚举会得到size大于 k k k的组合),回到递归上一层;
3、如果发现枚举到一个大于 t t t的数,也可以退出本层枚举,回到递归上一层(因为接下来枚举会得到更大的和,不会得到合法的解,所以可以直接退出)。

代码如下:

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 ( n k ) ) O(k{n\choose k}) O(k(kn)),空间复杂度 O ( k ) O(k) O(k)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值