当前位置: 首页 > 知识库问答 >
问题:

从数组中获取哪些值使给定数字的总和的算法

越麒
2023-03-14

我不知道搜索或谷歌它,所以我在这里问它。我有一个具有固定大小的整数数组,并且完全符合此逻辑。

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#方法中,它接受整数数组和一个整数值并返回包含从给定数组中求和此数字的整数的整数数组将是首选。

谢谢

共有3个答案

郭凯
2023-03-14

陈述你的要求的另一种方法是“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);
叶经略
2023-03-14

首先你应该注意到

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

这和寻找十进制数的二进制编码是一样的。你正在寻找的是一种算法,将十进制或基数为10的数字转换为二进制或基数为2的数字。

算法非常简单:

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;
}
穆建元
2023-03-14

如你所见,数字是以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;
    }
}

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

用法:

// 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);

但最好保持简单易读。

 类似资料:
  • 问题内容: 我正在为Android开发一个数学应用程序。在这些字段之一中,用户可以输入一个整数(无数字且大于0)。这个想法是获得所有可能的和,使之成为整数,而不加倍(在这种情况下为4 + 1 == 1 + 4)。唯一已知的是此int。 例如: 假设用户输入4,我希望该应用返回: 4 3 + 1 2 + 2 2 + 1 + 1 1 + 1 + 1 + 1 显然4 == 4,所以也应该加上。关于我应该

  • 问题内容: 说我有一个像这样的数组: 如何计算具有给定值的数字(在示例中为空白)? 而且有效吗?(大约十二个数组,每个数组包含数百个元素)此示例超时(超过30秒): 在这种情况下,空白元素的数量为3。 问题答案: 如何使用array_count _values来获得一个为您计算一切的数组?

  • 问题内容: 给定一个整数列表,我想找到哪个数字与我在输入中提供的数字最接近: 有什么快速的方法可以做到这一点吗? 问题答案: 如果不确定列表是否已排序,则可以使用内置函数,查找与指定数字之间的最小距离的元素。 请注意,它也可用于带有int键的字典,例如。此方法花费O(n)时间。 如果列表已经排序,或者您可以只对数组进行一次排序,请使用@Lauritz答案中所示的二等分方法,该方法只需要O(logn

  • 给定一个整数列表,我想找出哪个数字最接近我在输入中给出的一个数字: 有什么快速的方法可以做到这一点吗?

  • 返回数字数组的中值。 找到数字数组的中间值,使用 Array.sort() 对值进行排序。 如果 length 是奇数,则返回中间值数字,否则返回两个中间值数值的平均值。 const median = arr => { const mid = Math.floor(arr.length / 2), nums = [...arr].sort((a, b) => a - b); ret

  • 我想从这个代码中得到的数组中得到一个特定的数组数据: 结果是: 数组(1){[“用户”]= 我想得到的是用户名值,我尝试过这样的解决方案: 但它给了我这样的错误: 正在尝试获取非对象的属性“username” 如何解决这个问题?谢谢你的关注。