K Sum

Given n distinct positive integers, integer k (k <= n) and a number target.面试

Find k numbers where sum is target. Calculate how many solutions there are?数组

Example

Given [1,2,3,4], k = 2, target = 5.There are 2 solutions: [1,4] and [2,3].Return 2.优化

这是sum一系列问题中的终极版本,即求给出的n个数字中,取其中k个数字,最终和为target的组合有多少。spa

注意这题问的是有多少,并非要求给出全部的符合条件的k个数组的所有组合。按照前面的2 sum, 3sum, 4sum等题推理若是采用排序加双指针夹逼的方法,复杂度是O(n^(k-1))的,若是采用4sum这种利用2sum hashmap的作法,则最优的复杂度为有下降,可是4sum这种已经很复杂,对于更大的k为偶数的状况,会变得特别复杂。以上分析能够看出DP是这时候的好选择。指针

首先看这题自己的描述,n个取k个,组成和为target的状况,其实看描述很是像背包问题,容量是这里的target,可是背包问题自己不要求知道一共是多少个物体组成,且不须要知道方案数,因此二维的DP没法解决。咱们能够定义3维的DP状态:f[i][j][t]即前i个字母中取出j个能组成和为t的状况的种数。code

定义转换状态:f[i][j][t] = f[i-1][j][t] + f[i-1][j-1][t-nums[i-1]]和背包问题同样,咱们须要对取不取第i 个数字作一个判断。blog

初始化,这个是最tricky的地方,究竟如何初始化才对。首先数组中的全部的数字都是正数,且都不相同。因此f[i][1][A[i-1]]应该都是1. f[i][1][A[j]] = f[i-1][1][A[i]]+f[i-1][0][0], f[i-1][1][A[i]]确定是0,因此f[i-1][0][0]的值是1.能够先进行初始化。排序

最后的结果是f[n][k][target].复杂度为O(k*n*target).上述空间复杂度能够采用滚动数组优化为二维的(在n这一维度进行优化)。get

代码以下:hash

class Solution:
    """
    @param A: An integer array.
    @param k: a positive integer (k <= length(A))
    @param target: integer
    @return an integer
    """
    def kSum(self, A, k, target):
        n = len(A)
        dp = [[[0] * (target+1) for i in xrange(k+1)] for j in xrange(n+1)]
        for i in xrange(0, n+1):
            dp[i][0][0] = 1
        for i in xrange(1, n+1):
            for j in xrange(1, min(k+1,i+1)): #j的范围必定要注意 for t in xrange(1, target+1):
                    if t < A[i-1]:
                        dp[i][j][t] = dp[i-1][j][t]
                    else:
                        dp[i][j][t] = dp[i-1][j][t] + dp[i-1][j-1][t-A[i-1]]
        
        
        return dp[n][k][target]

这题三维的滚动数组优化比较困难,尝试了几回都有问题。后序再说。

这题难度比较高,面试中出现的几率比较低,但仍然是一道不错的DP题。

相关文章
相关标签/搜索