有1,2,3,4,5 这几个数,他们之间相加得10的结果有哪些。。
这题怎么做?用程序的话。
应该算是算法题了吧,我知道一共有2的5次方种排列方式,但是我不知道怎么用程序来表述这种排列方式,怎么循环出来?
也许给的示例太规律了。。。这样吧。。
假设有3,4,3,6,7,5,3这几个数,求用这几个数加起来等于9的结果,一个数只能用一次,这样结果就是
3+6=9
3+3+3=9
4+5=9
一楼的经测试可以,但是,我如果想计算小数呢?
假如数列是 double[] numbers = new double[] { 0.5, 0.1, 0.6, 0.3, 0.8, 0.06, 0.89, 0.02, 0.36 };
最后我想计算的结果是0.52,这样的话一楼的方法就行不通了。。晕。
这个不叫排列吧,加法满足交换律。我想的组合的算法, 这些被加数要么选中,要么不选中,放在一起,正好组成了1-2的n次方-1的数。全部没选中的不算, 然后只要把这些组合中相加结果为10的选出来就OK了, 哈哈,我的算法还是蛮好的:
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
int elementCount = numbers.Length;
int lastCombination = 2 << elementCount - 1;
int firstCombination = 1;
int sum;
const int targetSum = 10;
for (int i = firstCombination; i <= lastCombination; i++)
{
sum = 0;
for (int pos = 0; pos < elementCount; pos++)
{
if ((i & (1 << pos)) != 0) //当前组合第pos个数是否取中
sum += numbers[pos];
}
if (sum == targetSum)
{
for (int pos = 0; pos < elementCount; pos++)
if ((i & (1 << pos)) != 0)
Console.Write("{0}\t", numbers[pos]);
Console.WriteLine();
}
}
Console.ReadLine();
static class SumFinder
{
public static void FindSum(dynamic numbers, dynamic targetSum)
{
int elementCount = numbers.Length;
int lastCombination = 2 << elementCount - 1;
int firstCombination = 1;
dynamic sum;
for (int i = firstCombination; i <= lastCombination; i++)
{
sum = 0;
for (int pos = 0; pos < elementCount; pos++)
{
if ((i & (1 << pos)) != 0) //当前组合第pos个数是否取中
sum += numbers[pos];
}
if (sum == targetSum)
{
for (int pos = 0; pos < elementCount; pos++)
if ((i & (1 << pos)) != 0)
Console.Write("{0}\t", numbers[pos]);
Console.WriteLine();
}
}
Console.ReadLine();
}
}
//调用方法
SumFinder.FindSum(new double[] { 0.5, 0.1, 0.6, 0.3, 0.8, 0.06, 0.89, 0.02, 0.36 }, 0.52);
SumFinder.FindSum(new int[] { 1, 2, 3, 4, 5 }, 10);
以上代码可在.net 4.0及以上运行
@ChatinCode: 这个可以正常运行了。可以得到最后的答案了。。呵呵。。如果可以的话加以解释一下就好了。。
&符号和<<符号好像是用于位运算位比较的吧。。呵呵。。做网站2年了都没有接触 过这些。。
@牛腩: 最后这个代码少了些编译时的检查,因为使用了 dynamic。
@ChatinCode: 我自己已经改为可以在VS2008上运行了的。。呵呵。。得仔细看看为什么这样子得。。。主要是不知道位运算的意思。。。。
知道意思了也不知道为什么要那样子写。
@牛腩: 难道这个算法看不懂,你把这些数排成一排,因为是组合问题,就是说这些数中要取到的数可以标记为1,未取到的可标为0。这样不就对应了0到2的n次方-1的二进制数(n为数的个数),这些组合中取0个数的显然不行。i & (1 << pos)是取 i 的第 pos位数(二进制)。<< 二进制左移 , & 二进制与。不知道够明白吗??
用递归。这段代码应该还可以再优化的。
static void Main(string[] args)
{
var numbers = new []{ 1, 2, 3, 4, 5 };
int total = 10;
FindCombinations(numbers, total);
results.ForEach(r => Console.WriteLine(string.Join(",", r)));
Console.Read();
}
static List<int[]> results = new List<int[]>();
static Stack<int> currentResult = new Stack<int>();
static void FindCombinations(int[] numbers, int total)
{
if (numbers.Length == 0 && total == 0)
{
results.Add(currentResult.ToArray());
}
else
{
for (int i = 0; i < numbers.Length; i++)
{
var j = i;
currentResult.Push(numbers[j]);
FindCombinations(numbers.Skip(j + 1).ToArray(), total - numbers[j]);
currentResult.Pop();
}
}
}
问题不明确,什么叫“他们之间相加得10的结果有哪些。。”,是第一和第二个相加,还是前几个相加?提问,问题得明确吧?是否是"斐波那契数列"?
根据你的问题,先决条件,有几个数是固定的还是变量,和是定数还是变量?如果以现在给出的条件,就循环遍历,把所有数据放进数组,用n+(N+1)=9的方式做吧,n表示数组索引。