2010-04-12 35 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++; 
    } 
}