2010-04-12 37 views
8

我在微软的采访是下面给出的问题的一个不解的数字:形式使用连续数字

函数应该接受的范围内(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

你有什么迄今所做?您是否考虑过递归解决方案?这是明显的第一步。或者,您可以调查连续数字的和的性质,并使用它来计算解决方案模式(例如,如果x可以被3整除,则x是3个连续整数的和)。 – 2010-04-12 22:47:52

+6

17 = 7 + 8 19 = 8 + 9 ??? – K2so 2010-04-12 22:49:12

+0

您是否期望报告所有这样的组合(例如,也是9 = 2 + 3 + 4)或只有最短的这种序列? – jwismar 2010-04-12 23:00:58

回答

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

这是一些伪代码,找到所有的组合,如果存在的话:

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 

我测试它在红宝石(代码here),它似乎工作。我相信这个基本想法可以很容易地在C#中实现。

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 

希望这有助于。它符合做最简单的事情的原则,可能可行。

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); 
     } 
    } 
    } 
} 
+0

事实上,我们只需要检查我 2010-04-13 09:11:24

0

如果我们分割一个成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++; 
    } 
}