2010-04-12 4 views
8

Ero perplesso con una delle domande in un'intervista Microsoft, che è come indicato di seguito:forma un numero utilizzando numeri consecutivi

Una funzione dovrebbe accettare un intervallo (3-21) e dovrebbe stampare tutte le combinazioni di numeri consecutivi per formare ogni numero come indicato di seguito:

 
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

potresti per favore aiutarmi a formare questa sequenza in C#?

Grazie, Mahesh

+0

Cosa hai fatto finora? Hai considerato una soluzione ricorsiva? Questo è un primo passo ovvio.In alternativa puoi investigare le proprietà di somme di numeri consecutivi e usarlo per elaborare modelli di soluzioni (ad esempio, x è una somma di 3 numeri interi consecutivi iff x è divisibile per 3). –

+6

17 = 7 + 8 19 = 8 + 9 ??? – K2so

+0

Si prevede di riportare tutte queste combinazioni (ad esempio 9 = 2 + 3 + 4, anche) o solo la sequenza più breve? – jwismar

risposta

5

Così qui è una risposta diretta/ingenuo (in C++, e non testati, ma si dovrebbe essere in grado di tradurre). Esso utilizza il fatto che

1 + 2 + ... + n = n (n + 1)/2,

che probabilmente avete visto prima. Ci sono molte facili ottimizzazioni che possono essere fatte qui che ho omesso per chiarezza.


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

Questo è un codice pseudo di trovare tutte le combinazioni, se ne esistono:

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 

Una chiamata a all_consecutive_numbers (21) sarebbe stampare:

21 = 11 + 10 
21 = 8 + 7 + 6 
21 = 6 + 5 + 4 + 3 + 2 + 1 

ho provato in ruby ​​(codice here) e sembra funzionare. Sono sicuro che l'idea di base potrebbe essere facilmente implementata anche in C#.

0

Ecco qualcosa in Groovy, dovresti essere in grado di capire cosa sta succedendo. Non è il codice più efficiente e non crea le risposte nell'ordine che citi nella tua domanda (sembra che manchi qualcosa), ma potrebbe darti un inizio.

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]}" 
    } 
    } 
} 

Uscita per 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 

Spero che questo aiuti. È in qualche modo conforme al principio di fare la cosa più semplice che possa funzionare.

0

Mi piace questo problema. Ecco una chiazza di petrolio e un po 'misteriosa O (n) Soluzione:

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

Infatti, dobbiamo solo controllare i

0

se tagliare un in 2 cifre, quindi a = b + (b + 1) = 2 * b + (0 + 1)
se dividiamo a 3 cifre, allora a = b + (b + 1) + (b + 2) = 3 * b + (0 + 1 + 2)
...
se suddividiamo un numero in una cifra , quindi a = b + (b + 1) + ... + (b + n) = n b + (0 + 1 + n-1)
l'ultimo risultato è a = n
b + n * (n-1)/2, a, b, n sono tutti inti.
quindi O (N) algoritmo è:

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