获取哪些值使数组中给定数字的总和的算法
Algorithm to get which values make sum of a given number from array
我不知道搜索或google所以我在这里问。
我有一个固定大小的整数数组,完全符合这个逻辑。
sample [1,2,4,8,16,32]
现在我得到一个数字,例如 26。我将找到其总和等于该数字的数字,在本例中为 [2,8,16]
对于 20 的数字,它将是 [4,16]
对于 40 是 [8,32]
对于 63,它是所有这些数字 [1,2,4,8,16,32]
正确的算法是什么?
我很清楚,总有这个数字是前一个值的两倍的延续。
以及只有给定数组中的数字总和为给定数字,并且每个数字将仅使用一次或 none
如果在 C# 方法中采用整数数组和一个整数值,并且 returns 包含对给定数组中此数字求和的整数的整数数组将是首选。
谢谢
如您所见,数字是以 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;
}
}
此方法将检查设置了哪些位并将它们 return 作为可枚举的。 (可以转换为列表数组)
用法:
// 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);
但最好保留它simpel/readable。
首先你应该注意到
( 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;
}
我不太明白“采用整数数组”部分,因为这种求和的创建仅适用于 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());
}
另一种表达您的要求的方法是 "What are the unique powers of 2 that sum to a given integer?" 由于计算机本身以 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);
我不知道搜索或google所以我在这里问。 我有一个固定大小的整数数组,完全符合这个逻辑。
sample [1,2,4,8,16,32]
现在我得到一个数字,例如 26。我将找到其总和等于该数字的数字,在本例中为 [2,8,16]
对于 20 的数字,它将是 [4,16]
对于 40 是 [8,32]
对于 63,它是所有这些数字 [1,2,4,8,16,32]
正确的算法是什么?
我很清楚,总有这个数字是前一个值的两倍的延续。 以及只有给定数组中的数字总和为给定数字,并且每个数字将仅使用一次或 none
如果在 C# 方法中采用整数数组和一个整数值,并且 returns 包含对给定数组中此数字求和的整数的整数数组将是首选。
谢谢
如您所见,数字是以 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;
}
}
此方法将检查设置了哪些位并将它们 return 作为可枚举的。 (可以转换为列表数组)
用法:
// 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);
但最好保留它simpel/readable。
首先你应该注意到
( 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;
}
我不太明白“采用整数数组”部分,因为这种求和的创建仅适用于 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());
}
另一种表达您的要求的方法是 "What are the unique powers of 2 that sum to a given integer?" 由于计算机本身以 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);