获取哪些值从数组中得到给定数字之和的算法

时间:2017-08-02 13:29:46

标签: c# arrays algorithm math linear-algebra

我不知道要搜索或谷歌,所以我在这里问。 我有一个固定大小的整数数组,正是这个逻辑。

sample [1,2,4,8,16,32]

现在给我一个例如26的数字。我会找到这个数字的数字,这个数字是[2,8,16]

对于数字20,它将是[4,16]

为40,它是[8,32]

对于63而言,所有这些数字都是[1,2,4,8,16,32]

适当的算法是什么?

我严格地知道,这个数字始终是前一个值的两倍。 以及只有给定数组中的数字将总和给定数字,每个数字仅用于一次或不用

如果它将在C#方法中获取整数数组和一个int值并返回包含整数的整数数组,这些整数将从给定数组中总结这个数字。

谢谢

4 个答案:

答案 0 :(得分:4)

如您所见,该数字为base-2,这意味着您可以轻松使用shift

你可以试试这个:

private IEnumerable<int> FindBits(int value)
{
    // check for bits.
    for (int i = 0; i < 32; i++)
    {
        // shift 1 by i
        var bitVal = 1 << i;   // you could use (int)Math.Pow(2, i); instead
        // check if the value contains that bit.
        if ((value & bitVal) == bitVal)
            // yep, it did.
            yield return bitVal;
    }
}

此方法将检查设置了哪些位并将它们作为不可数字返回。 (可以转换为列表数组)

用法:

// find the bits.
var res = FindBits(40).ToArray();

// format it using the string.join
var str = $"[{string.Join(",", res)}]";

// present the results
Console.WriteLine(str);

[8,32]

中的结果

额外信息:

                          counter
00000001 =   1     = 1 << 0
00000010 =   2     = 1 << 1 
00000100 =   4     = 1 << 2
00001000 =   8     = 1 << 3
00010000 =  16     = 1 << 4
00100000 =  32     = 1 << 5
01000000 =  64     = 1 << 6
10000000 = 128     = 1 << 7

不是编写所有组合,而是创建一个for循环来执行计数器。

一些额外的无意义:

如果你喜欢lambda,你可以用这个代替FindBits:

private Func<int, IEnumerable<int>> FindBits = (int value) => Enumerable
    .Range(0, 31)
    .Select(i => 2 << i).Where(i => (value & i) == i);

但最好是保持简洁/可读。

答案 1 :(得分:1)

首先你应该注意到

 ( 1    2    4    8    16 ... ) = (2^0  2^1  2^2  2^3  2^4 ... )

这与查找十进制数的二进制编码相同。您正在寻找的是一种将十进制或十进制数转换为二进制或二进制数的算法。

算法非常简单:

public List<int> dec_to_bin(int num)
{
    List<int> return_list = new List<int>();
    int index = 0; 
    int remainder = num;
    int bit = 0;

    while (remainder > 0)
    {
        bit = remainder % 2;

        if (bit == 1 )
        {
            return_list.Add((int)Math.Pow(2, index));
        }

        remainder = remainder / 2; 
        index = index + 1;
   }

   return return_list;
}

然而,有一种更好的方法就是使用已经是二进制的数字的基础编码。

public List<int> dec_to_bin(int num)
{
    List<int> return_list = new List<int>();
    int value = 1; 

    while( value < num )
    {
         if( (value & num) == value )
         {
             return_list.Add(value);
         }
         value = value * 2; 
    }
    return return_list;
}

答案 2 :(得分:1)

表达需求的另一种方法是“ 2的幂是否等于给定整数?” 由于计算机本身就是2的幂,因此大多数计算机中都有内置的好东西。语言非常简洁地做到这一点。

作为奖励,您可以使用现有的.Net类型和方法来消除编写自己的循环的需要。

这是一种方法:

IEnumerable<int> GetCompositePowersOf2(int input) =>
    //convert to enumerable of bools, one for each bit in the 
    //input value (true=1, false=0)
    new BitArray(new[] { input }).Cast<bool>()
    // get power of 2 corresponding to the position in the enumerable 
    // for each true value, gets 0 for false values.
    .Select((isOne, pos) => isOne ? (1 << pos) : 0)
    //filter out the 0 values
    .Where(pow => pow > 0);

答案 3 :(得分:0)

我没有完全得到“采取一系列的整数”部分,因为这种总和的创建仅适用于2的幂数。

    private int[] count (int num)
    {

        int factor = 0;
        List<int> facts = new List<int>();
        while (num > 0)
        {
            int counter = 0;
            int div = num;
            int remainder = 0;
            while (remainder == 0)
            {
                remainder = div % 2;
                div = div / 2;
                counter++;
            }
            factor = 1;
            for (int i = 1; i < counter; i++) 
                factor *= 2;
            num = num - factor;
            facts.Add(factor);
        }

        return (facts.ToArray());
    }