将一组数字分成差值最小的两部分

发布于 2024-10-16 01:31:31 字数 161 浏览 3 评论 0原文

将一组数字(n 个数字)划分为 2 个子集,使得子集 1 中的数字之和与子集 2 中的数字之和相差最小。还需要满足以下条件:

  • 如果 n = 2k,则每个子集有 k成员
  • 如果 n = 2k+1,则一个子集有 k 个成员,另一个子集有 k+1 个成员。

Partition a set of numbers (n numbers) into 2 subset so that the sum of numbers in subset 1 has the least difference with the sum of numbers in subset 2. Also the following condition is necessary:

  • If n = 2k, each subset has k members
  • If n = 2k+1, one subset has k members and the other has k+1 members.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

垂暮老矣 2024-10-23 01:31:31

这个问题是NP完全问题。 http://en.wikipedia.org/wiki/Partition_problem
您将不得不通过暴力找到解决方案。

(任意大小分区的分区问题相当于等大小分区的问题 - 只需将一个大值 C 添加到所有数字并要求差值小于 C...)

您可能还想看看http://en.wikipedia.org/wiki/Subset_sum_problem

This problem is NP-complete. http://en.wikipedia.org/wiki/Partition_problem
You will have to find solutions by brute-force.

(The Partition problem with partitions of arbitrary size is equivalent to the problem with equal size partitions - just add a large value C to all numbers and demand that the difference be less than C...)

You might also want to have a look at the http://en.wikipedia.org/wiki/Subset_sum_problem

深海里的那抹蓝 2024-10-23 01:31:31

此答案复制自http://www.careercup.com/question?id=10244832

由于本质上是 NP 困难,该解决方案属于复杂度为 O(n^2W) 的伪多项式时间算法,其中 n = 元素数,W = 元素之和。

//constraints: n is even
void fun (int items[], int n)
{
    int total = accumulate (items, items+n, 0) / 2;
    int maxSubsetSz = n/2 ;

    vector< vector<int> > T (maxSubsetSz+1, vector<int> (total+1, 0) );

    //T[i][j] is set if there exists subset of size i that sum up to j
    T[0][0] = 1;    

    for(int i = 0; i < n; i++) //consider taking i-th item      
       for(int k = maxSubsetSz-1; k >= 0; k--) //each item must be taken once, hence loop backwards
           for(int j = 0; j <= total-items[i]; j++)  
               if ( T[k][j] && items[i]+j <= total )                        
                     T [k+1] [j+items[i]] = 1;

    for(int j = total; j >= 1; j--)
       if ( T [maxSubsetSz][j] ) {
        cout << "sum : " << j << endl; 
        break;
    }
}

@hugomg提供的答案具有相同的时间复杂度,因为大值C至少应与W(=元素之和)一样大,从而使背包问题的时间复杂度 = O(n*(W + nW)) = O(n^2*W)

This answer is copied from http://www.careercup.com/question?id=10244832

Being NP-hard by nature, the solution falls into pseudo-polynomial time algorithm with complexity O(n^2W) where n = # of elements, W = sum of elements.

//constraints: n is even
void fun (int items[], int n)
{
    int total = accumulate (items, items+n, 0) / 2;
    int maxSubsetSz = n/2 ;

    vector< vector<int> > T (maxSubsetSz+1, vector<int> (total+1, 0) );

    //T[i][j] is set if there exists subset of size i that sum up to j
    T[0][0] = 1;    

    for(int i = 0; i < n; i++) //consider taking i-th item      
       for(int k = maxSubsetSz-1; k >= 0; k--) //each item must be taken once, hence loop backwards
           for(int j = 0; j <= total-items[i]; j++)  
               if ( T[k][j] && items[i]+j <= total )                        
                     T [k+1] [j+items[i]] = 1;

    for(int j = total; j >= 1; j--)
       if ( T [maxSubsetSz][j] ) {
        cout << "sum : " << j << endl; 
        break;
    }
}

The answer provided by @hugomg has the same time complexity because the large value C should be at least as large as W (= sum of elements), thus make the time complexity of knapsack problem = O(n*(W + nW)) = O(n^2*W)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文