【问题标题】:Given a list of n integers , find the minimum subset sum greater than X给定一个包含 n 个整数的列表,找到大于 X 的最小子集和
【发布时间】:2017-04-15 09:24:17
【问题描述】:

给定一组未排序的数组形式的整数,找到大于或等于 const 整数 x 的最小子集总和。

例如:- 我们的集合是 {4 5 8 10 10}x=15 所以最接近x>=x is {5 10}的最小子集总和

我只能想到一个简单的算法,它列出集合的所有子集并检查子集的总和是否为>=x 和最小值,但它是一个指数算法并列出所有子集需要 O(2^N)。我可以使用动态规划在多项式时间内求解吗?

【问题讨论】:

  • 最小子集是指总和最接近x的子集,还是任何子集>=x但元素数量最少?
  • @biziclop 我的意思是最接近 x 的子集总和 >=x
  • 如果你能解决这个问题,你也有解决子集和问题的办法。因此,这个问题是 NP 难的。

标签: arrays algorithm subset dynamic-programming subset-sum


【解决方案1】:

如果你所有数字的总和是S,而你的目标数字是X,你可以把问题改写成这样:你能选择小于或等于@987654324的数字的最大子集吗@?

你有knapsack problem 的一个特例,它的权重和价值是相等的。

这是个坏消息,因为这意味着您的问题是 NP 难题,但从好的方面来说,您可以使用 KP 的动态规划解决方案(它仍然不是多项式)。或者您可以尝试 KP 的多项式近似,如果这对您来说足够好的话。

【讨论】:

    【解决方案2】:

    如前所述,这是 NP 完全的。另一种理解方式是,如果可以在多项式时间内解决这个问题,那么子集和问题也可以在多项式时间内解决(如果存在解决方案,那么它将是相同的)。

    【讨论】:

      【解决方案3】:

      我认为其他答案不正确。您的问题实际上是 0-1 背包问题(即没有重复)的变体,即 solvable in polynomial time with dynamic programming。您只需要按照@biziclop 的答案制定您的标准。

      【讨论】:

      • 严格来说,动态规划算法根据定义不是多项式时间;它被称为“伪多项式时间”。维基百科说:“O(nW) 复杂度与背包问题是 NP 完全的事实并不矛盾,因为 W 与 n 不同,在问题的输入长度上不是多项式。问题的 W 输入与 W 中的位数成正比,log W,而不是 W 本身。” en.wikipedia.org/wiki/… 接受的答案还提到了动态规划算法。
      【解决方案4】:

      贪婪的方法怎么样?

      首先我们按降序对列表进行排序。然后我们递归地弹出排序列表的第一个元素,从 x 中减去它的值,然后重复直到 x 为 0 或更小。

      在伪代码中:

      sort(array)
      current = 0
      solution = []
      while current < x:
          if len(array) < 0:
              return -1 //no solution possible
          current += array[0]
          solution.append(array.pop(0))
      return solution
      

      【讨论】:

        【解决方案5】:

        我正在修改 DP。我想到了这个问题。然后我搜索并得到了这个问题,但没有正确的答案。

        所以这里是完整的代码(以及 cmets ):希望它有用。

        sample image of table //与子集和完全相同的概念(找到子集和的最小差)

        public class Main
        {
        public static int minSubSetSum(int[] arr,int n,int sum,int x){
            boolean[][] t=new boolean[n+1][sum+1];
            //initailization if n=0 return false;
                for(int i=0;i<sum+1;i++)
                    t[0][i]=false;
            //initialization if sum=0 return true because of empty set (a set can be empty)
                for(int i=0;i<n+1;i++)
                    t[i][0]=true;   //here if(n==0 && sum==0 return true) has been also initialized
            
            //now DP top-down
            
            for(int i=1;i<n+1;i++)
                for(int j=1;j<sum+1;j++)
                {
                    if(arr[i-1]<=j)
                        t[i][j]=t[i-1][j-arr[i-1]] || t[i-1][j]; // either include arr[i-1] or not 
                    else
                        t[i][j]=t[i-1][j]; //not including arr[i-1] so sum is not deducted from j
                }
                
            //now as per question we have to take all element as it can be present in set1
            //if not in set1 then in set2 ,so always all element will be a member of either set
            // so we will look into last row(when i=n) and we have to find min_sum(j)
            
            int min_sum=Integer.MAX_VALUE;
            for(int j=x;j<=sum;j++)
                if(t[n][j]==true){      //if in last row(n) w.r.t J , if the corresponding value true then
                    min_sum=j;    //then that sum is possible
                    break;
                    }
                    
            if(min_sum==Integer.MAX_VALUE)
                return -1;// because that is not possible
                
            return min_sum;
        }
        public static void main(String[] args) {
            int[] arr=new int[]{4,5,8,10,10};
            int x=15;
            int n=arr.length;
            int sum=0;
            for(int i=0;i<n;i++)
                sum=sum+arr[i];
           System.out.println("Min sum can formed greater than X is");
           
           int min_sum=minSubSetSum(arr,n,sum,x);
           System.out.println(min_sum);
            
        }
        

        }

        由于问题是 N-P 完全的,因此使用 DP 时间复杂度降低到 T(n)=O(n*sum) 和空间复杂度=O(n*sum);

        【讨论】:

          猜你喜欢
          • 2021-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多