【问题标题】:Write number as sum of given integers将数字写为给定整数的总和
【发布时间】:2013-03-27 19:07:41
【问题描述】:

这就是问题所在。

将给定数字 N 写为给定数字的总和,仅使用加法和减法。

这是一个例子:

N = 20
Integers = 8, 15, 2, 9, 10

20 = 8 + 15 - 2 + 9 - 10。

这是我的想法;

第一个想法是使用蛮力,交替加减。首先,我计算组合的数量及其 2^k(其中 k 是整数的数量),因为我只能交替使用减号和加号。然后我遍历从 1 到 2^k 的所有数字,并将其转换为二进制形式。对于任何 1,我使用加号,对于任何 0,我使用减号。通过一个示例(使用上面的示例),您会更容易理解。

The number of combinations is: 2^k = 2^5 = 32.
Now I run through all numbers from 1 to 32. 
So i get: 1=00001, that means: -8-15-2-9+10 = -24 This is false so I go on.
2 = 00010, which means: -8-15-2+9-10 = -26. Also false.

这种方法效果很好,但是当整数数量太大时,它需要的时间太长。

这是我的 C++ 代码:

#include <iostream>
#include <cmath>
using namespace std;
int convertToBinary(int number) {
    int remainder;
    int binNumber = 0;
    int i = 1;
    while(number!=0)
    {
        remainder=number%2;
        binNumber=binNumber + (i*remainder);
        number=number/2;
        i=i*10;
    }
    return binNumber;
}
int main()
{
    int N, numberOfIntegers, Combinations, Binary, Remainder, Sum;
    cin >> N >> numberOfIntegers;
    int Integers[numberOfIntegers];
    for(int i = 0; i<numberOfIntegers; i++)
    {
        cin >>Integers[i];
    }
    Combinations = pow(2.00, numberOfIntegers);
    for(int i = Combinations-1; i>=Combinations/2; i--) // I use half of the combinations, because 10100 will compute the same sum as 01011, but in with opposite sign.
    {
        Sum = 0;
        Binary = convertToBinary(i);
        for(int j = 0; Binary!=0; j++)
        {
            Remainder = Binary%10;
            Binary = Binary/10;
            if(Remainder==1)
            {
                Sum += Integers[numberOfIntegers-1-j];
            }
            else
            {
                Sum -= Integers[numberOfIntegers-1-j];
            }
        }
        if(N == abs(Sum))
        {
            Binary = convertToBinary(i);
            for(int j = 0; Binary!=0; j++)
            {
                Remainder = Binary%10;
                Binary = Binary/10;
                if(Sum>0)
                {
                    if(Remainder==1)
                    {
                        cout << "+" << Integers[numberOfIntegers-1-j];
                    }
                    else
                    {
                        cout << "-" << Integers[numberOfIntegers-1-j];
                    }
                }
                else
                {
                    if(Remainder==1)
                    {
                        cout << "-" << Integers[numberOfIntegers-1-j];
                    }
                    else
                    {
                        cout << "+" << Integers[numberOfIntegers-1-j];
                    }
                }
            }
            break;
        }
    }
    return 0;
}

【问题讨论】:

  • 请搜索现有的问题,因为我记得之前多次看到过这个问题。
  • 正如 Ben 所说,这个(或类似的)已经被问过很多次了。
  • 我看过您发布的所有示例,但我认为这有点不同。几乎每个示例都是子集问题。这个正在使用所有给定的数字并获得想要的数字。另外,我从来没有真正找到可以减去的例子。
  • 为什么要将组合数转换为二进制并除以十进制的10?

标签: c++ binary numbers sum combinations


【解决方案1】:

由于这是典型的作业,我不会给出完整的答案。但是考虑一下:

K = +a[1] - a[2] - a[3] + a[4]

可以改写为

a[0] = K
a[0] + a[2] + a[3] = a[1] + a[4]

现在两边都有正常的子集总和。

【讨论】:

    【解决方案2】:

    所以你担心的是你的复杂性。

    让我们分析一下可以进行哪些优化。

    给定 a[n] 中的 n 个数字和目标值 T;

    而且可以肯定的是,加减法的一种组合会给你 T ;

    所以 Sigma(m*a[k]) =T where( m =(-1 or 1) and 0 >= k >= n-1 )

    这只是意味着..

    可以写成

    (数组中一些数字的总和)=(数组中剩余数字的总和)+ T

    就像你的情况..

    8+15-2+9-10=20可以写成

    8+15+9=20+10+2

    所以包括目标在内的所有数字的总和 = 64 // 我们可以计算出 .. :)

    所以一半是 32

    如果进一步写成 20+(somthing)=32 在这种情况下为 12 (2+10)。

    您的问题可以简化为在这种情况下查找总和为 12 的数组中的数字

    所以你的问题现在可以减少为找到总和为 k 的数字组合(你可以按照上面的描述计算 k=12 。)对于它的复杂性是 O(log (n )) n 作为数组的大小, 请记住,您必须对数组进行排序并使用基于二进制搜索的算法来获取 O(log(n))。

    所以复杂度可以从 O(2^n) 到 O((N+1)logN) 包括排序在内。

    【讨论】:

    • 如何检查哪个组合计算出 12 的总和?它减少了时间,这是显而易见的,但仍然不足以检查每个组合。不管怎样,谢谢你帮助我
    • 让排序后的数字是..!! 1,2,8,9,10,12,14,21 假设您需要计算 25 的总和 A) 开始找到小于或等于目标的数字(此处为 25),此处为 21.. 重复该步骤A for Target as (25-21) you can't find 4 or less so go to next number which is 14 Step A(11 as target 25-14) Step A(11 -10(as 10 is less than to 11 you can find ..)) 找到步骤 A(目标为 1),因此我们可以通过 (1, 10, 14) 得到总和 25
    【解决方案3】:

    这需要您提供的静态输入,我使用核心 java 编写

      public static void main(String[] args) {
    
        System.out.println("Enter number");
    
        Scanner sc = new Scanner(System.in);
    
        int total = 0;
    
        while (sc.hasNext()) {
    
    
            int[] array = new int[5] ;
    
            for(int m=0;m<array.length;m++){
                array[m] = sc.nextInt();
            }
    
             int res =array[0];
                for(int i=0;i<array.length-1;i++){
    
                        if((array[i]%2)==1){
                                res = res - array[i+1];
                        }
                        else{
                        res =res+array[i+1];
                        }
                }
                System.out.println(res);
        }
    }
    

    【讨论】:

    • 请不要用 Java 代码(或其他方式)回答 C++ 问题。最好解释一下您提供的代码的作用以及它为什么/如何解决提问者的问题/问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多