【问题标题】:dynamic programming - subset sum - reconstruct paths动态规划 - 子集和 - 重构路径
【发布时间】:2017-12-03 16:08:54
【问题描述】:

给定一组非负整数和一个值总和,确定给定集合中是否存在总和等于给定总和的子集。

例如:

set = {1,2,5,7}
sum = 8
=> true

我实际上用这段代码解决了这个问题:

public boolean isSubsetSum(int[] set, int sum) {
    Arrays.sort(set);
    boolean[][] memo = new boolean[set.length+1][sum+1];
    for (int i = 0; i < memo.length; i++) {
        memo[i][0] = true;
    }
    for (int i = 1; i < memo.length; i++) {
        for (int j = 1; j < memo[i].length; j++) {
            if (set[i-1] > j) {
                memo[i][j] = memo[i-1][j];
            } else {
                memo[i][j] = memo[i-1][j] || memo[i-1][j-set[i-1]];
            }
        }
    }
    return memo[memo.length-1][memo[memo.length-1].length-1];
}

但是,现在我想重构构成给定总和的所有可能组合。

是否可以从我的记忆矩阵中做到这一点,还是我必须以不同的方式做到这一点?

【问题讨论】:

    标签: java dynamic-programming


    【解决方案1】:

    创建一个名为 take[i][j] 的新 DP 表,它是布尔值。如果您将i-th 元素作为子集总和j,这是正确的。您将其与正常的备忘录表同时填写:

    for (int i = 1; i < memo.length; i++) {
        for (int j = 1; j < memo[i].length; j++) {
            if (memo[i-1][j]){
                //no need to take ith elements, first i-1 have sum j
                take[i][j] = false;
                memo[i][j] = true;
            }
            else if (j-set[i-1] >= 0 && memo[i-1][j-set[i-1]]){
                //take ith element, and search for set of size j-set[i-1] in 1..i-1
                take[i][j] = true;
                memo[i][j] = true;
            }
            else{
                //neither memo[i-1][j] or memo[i-1][j-set[i-1]] valid, so no way to make sum
                take[i][j]=false;
                memo[i][j]=false;
            }
    
        }
    }
    

    最后,要重构一个解决方案,您可以从:

    int i =set.length
    int j = sum
    while (i>=0 && j>=0){
      if (take[i][j]){
        print(set[i])
        j = j - set[i]
        i=i-1
      }
      else{
        i=i-1
      }
    }
    

    您可以将这一点推广到所有解决方案集。

    【讨论】:

    • 感谢您的回答!为什么 memo[i][j] 在 else 情况下设置为 true,如果没有办法不求和?
    • @cmplx96 抱歉,写得很快,所以不够仔细。是的,在 else 中两者都应该是 false。
    猜你喜欢
    • 1970-01-01
    • 2015-03-24
    • 2018-06-11
    • 1970-01-01
    • 2015-05-06
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多