2015-08-17 8 views
9

suppongo, dato alcuni numeriTrovare il numero di coppie in cui il primo elemento è divisibile per secondo elemento

8, 7, 6, 5, 4, 3, 2 

dovete trovare tutte le coppie in cui (a, b)a compare nella lista prima b e a%b = 0.

Ecco, queste coppie sono:

(8, 4), (8, 2), (6, 3), (6, 2), (4, 2) 

Esiste un algoritmo migliore di O (n)?

+0

C'è qualche vincolo? Quanto è grande ogni numero? –

+0

ogni elemento è compreso tra 1 e 10^5 –

+0

no, i numeri possono essere qualsiasi ordine casuale –

risposta

0

L'utilizzo della programmazione dinamica può essere risolto con la complessità O (nlogn). Simile al problema della denominazione della moneta.

prega di fare riferimento al seguente link per soluzione problema monete di taglio Coin Denomination problem

+0

Questo sembra vago al meglio. Come gestisci i valori duplicati? –

1

È possibile precompute un elenco di tutti i divisori dei possibili numeri interi in input = O (n^1.5)

Dopo di che un'iterazione su l'input, tenendo traccia di quanto vale un numero (cioè quante coppie si formerebbero).

per ogni numero in entrata è necessario iteratore su tutti i suoi divisori, cioè O (n^1.5)

Così la complessità totale è O (n^1.5) dove n è il massimo di 100000 e la dimensione del tuo contributo.

class Denominators {               

    public static void main (String[] a) {         
     int maxValue = 100000;            
     int[] problemSet = {8, 7, 6, 5, 4, 3, 2};       
     System.out.println (new Denominators().solve(problemSet, maxValue)); 
    }                  


    int solve (int[] problemSet, int maxValue) {        
     List<List<Integer>> divisors = divisors(maxValue);     
     int[] values = new int[maxValue + 1];        
     int result = 0;              
     for (int i : problemSet) {           
      result += values[i];            
      for (int d : divisors.get(i)) {         
       values[d]++;             
      }                
     }                 
     return result;              
    }                  


    private List<List<Integer>> divisors (int until) {      
     List<List<Integer>> result = new ArrayList<>();      
     for (int i = 0; i <= until; i++) {         
      result.add (new ArrayList<Integer>());       
     }                 
     for (int i = 1; i * i <= until; i++) {        
      for (int j = i; j * i <= until ; j++) {       
       result.get (i * j).add(i);         
       if (i != j) result.get (i * j).add(j);      
      }                
     }                 
     return result;              
    }                  

} 
+0

"Per ogni numero nell'input è necessario iteratore su tutti i suoi divisori, anche O (n log n)." In effetti un numero può avere molto più di O (log n) divisori, quindi penso che questo sia più simile a O (n^(1 + eps)) per alcuni eps <1/2. Tuttavia, il numero più alto di divisori nell'intervallo 1..10^5 è 29, che è piuttosto piccolo –

+0

Oh, in realtà sono 128, non 29, quindi dovresti considerare che: http://oeis.org/A066150 Apparentemente n^(1/3) è un'approssimazione piuttosto utile del numero di divisori di n per small-ish n –

+0

@NiklasB., Dove hai trovato che "il più alto numero di divisori nell'intervallo 1..10^5 è 29", (FYI: no di divisori di 720 è 30) – vish4071

Problemi correlati