我对微软采访中的一个问题感到困惑,如下所示:
一个函数应该接受一个范围(3 - 21)并且它应该打印所有连续的数字组合以形成如下所示的每个数字:
3 = 1+2 5 = 2+3 6 = 1+2+3 7 = 3+4 9 = 4+5 10 = 1+2+3+4 11 = 5+6 12 = 3+4+5 13 = 6+7 14 = 2+3+4+5 15 = 1+2+3+4+5 17 = 8+9 18 = 5+6+7 19 = 9+10 20 = 2+3+4+5+6 21 = 10+11 21 = 1+2+3+4+5+6
你能帮我在C#中形成这个序列吗?
谢谢, 马赫什
答案 0 :(得分:5)
所以这是一个直截了当/天真的答案(在C ++中,没有经过测试;但你应该能够翻译)。它使用的事实是
1 + 2 + ... + n = n(n + 1)/ 2,
你可能以前见过的。这里有很多简单的优化,为了清楚起见,我省略了这些优化。void WriteAsSums (int n)
{
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
if (n = (j * (j+1) - i * (i+1))/2) // then n = (i+1) + (i+2) + ... + (j-1) + j
{
std::cout << n << " = ";
for (int k = i + 1; k <= j; k++)
{
std::cout << k;
if (k != j) // this is not the interesting bit
std::cout << std::endl;
else
std::cout << " + ";
}
}
}
}
}
答案 1 :(得分:1)
这是一些伪代码,用于查找所有组合(如果存在):
function consecutive_numbers(n, m)
list = [] // empty list
list.push_back(m)
while m != n
if m > n
first = list.remove_first
m -= first
else
last = list.last_element
if last <= 1
return []
end
list.push_back(last - 1)
m += last - 1
end
end
return list
end
function all_consecutive_numbers(n)
m = n / 2 + 1
a = consecutive_numbers(n, m)
while a != []
print_combination(n, a)
m = a.first - 1
a = consecutive_numbers(n, m)
end
end
function print_combination(n, a)
print(n + " = ")
print(a.remove_first)
foreach element in a
print(" + " + element)
end
print("\n")
end
对all_consecutive_numbers(21)的调用将打印:
21 = 11 + 10
21 = 8 + 7 + 6
21 = 6 + 5 + 4 + 3 + 2 + 1
我在ruby中测试了它(代码here),它似乎有效。我确信基本的想法也可以很容易地在C#中实现。
答案 2 :(得分:0)
这是Groovy中的一些内容,您应该能够理解正在发生的事情。它不是最有效的代码,也不会按照你引用问题的顺序创建答案(虽然你似乎错过了一些),但它可能会给你一个开始。
def f(a,b) {
for (i in a..b) {
for (j in 1..i/2) {
def (sum, str, k) = [ 0, "", j ]
while (sum < i) {
sum += k
str += "+$k"
k++
}
if (sum == i) println "$i=${str[1..-1]}"
}
}
}
f(3,21)
的输出是:
3=1+2
5=2+3
6=1+2+3
7=3+4
9=2+3+4
9=4+5
10=1+2+3+4
11=5+6
12=3+4+5
13=6+7
14=2+3+4+5
15=1+2+3+4+5
15=4+5+6
15=7+8
17=8+9
18=3+4+5+6
18=5+6+7
19=9+10
20=2+3+4+5+6
21=1+2+3+4+5+6
21=6+7+8
21=10+11
希望这会有所帮助。它有点符合做最简单的事情的原则。
答案 3 :(得分:0)
我喜欢这个问题。这是一个光滑而略带神秘的O(n)解决方案:
void DisplaySum (int n, int a, int b)
{
std::cout << n << " = ";
for (int i = a; i < b; i++) std::cout << i << " + ";
std::cout << b;
}
void WriteAsSums (int n)
{
N = 2*n;
for (int i = 1; i < N; i++)
{
if (~(N%i))
{
int j = N/i;
if (j+i%2)
{
int a = (j+i-1)/2;
int b = (j-i+1)/2;
if (a>0 & a<b) // exclude trivial & negative solutions
DisplaySum(n,a,b);
}
}
}
}
答案 4 :(得分:0)
如果我们将a切成2位数,则a = b +(b + 1)= 2 * b +(0 + 1)
如果我们将a切成3位数,则a = b +(b + 1)+(b + 2)= 3 * b +(0 + 1 + 2)
...
如果我们将a切成n位数,则a = b +(b + 1)+ ... +(b + n)= n b +(0 + 1 + n-1)
最后一个结果是a = n b + n *(n-1)/ 2,a,b,n都是整数。
所以O(N)算法是:
void seq_sum(int a)
{
// start from 2 digits
int n=2;
while(1)
{
int value = a-n*(n-1)/2;
if(value < 0)
break;
// meet the quotation we deduct
if( value%n == 0 )
{
int b=value/n;
// omit the print stage
print("......");
}
n++;
}
}