2016-07-13 1 views
0

Ich muss dieses Array in O (n) time und O (1) space sortieren.Sortiere ein Array, dessen Elemente von 1 bis n reichen, wobei ein Element fehlt und eines wiederholt wird

Ich weiß, wie man ein Array in O (n) sortiert, aber das funktioniert nicht mit fehlenden und wiederholten Zahlen. Wenn ich die wiederholten und fehlenden Zahlen zuerst finde (es kann in O (n) gemacht werden) und dann sortieren, erscheint das teuer.

static void sort(int[] arr) 
{ 
    for(int i=0;i<arr.length;i++) 
    { 
     if(i>=arr.length) 
      break; 
     if(arr[i]-1 == i) 
      continue; 
     else 
     { 
     while(arr[i]-1 != i) 
     { 
      int temp = arr[arr[i]-1]; 
      arr[arr[i]-1] = arr[i]; 
      arr[i] = temp; 
     } 
     } 
    } 
} 
+0

Versuchen Sie die fehlende Zahl oder die wiederholte Zahl finden. Sobald Sie das getan haben, können Sie das Array leicht sortieren. Es gibt O (n) -Methoden, um ein Duplikat in einem Array zu finden. –

+0

Ja, ich weiß das, aber können wir es nicht in einem Durchlauf tun, ohne diese Elemente zu finden? –

+0

Ja, das Finden der fehlenden und der wiederholten Elemente in O (n) ist genau das Problem, das Sie lösen müssen. Vielleicht, wenn Sie herausfinden können, welche der beiden größer ist, wird es ein bisschen einfacher, sie zu finden. –

Antwort

0
void sort() { 
    for (int i = 1; i <= N; ++i) { 
    while (a[i] != a[a[i]]) { 
     std::swap(a[i], a[a[i]]); 
    } 
    } 

    for (int i = 1; i <= N; ++i) { 
    if (a[i] == i) continue; 
    for (int j = a[i] - 1; j >= i; --j) a[j] = j + 1; 
    for (int j = a[i] + 1; j <= i; ++j) a[j] = j - 1; 
    break; 
    } 
} 

Erläuterung: Lasst uns m die fehlende Zahl bezeichnen und d die duplizierten Nummer

  • Bitte beachten Sie, in der while Schleife ist die Abbruchbedingung a[i] != a[a[i]], die sowohl a[i] == i abdeckt und a[i] ist ein Duplikat.
  • Nach dem ersten für, jedes nicht-Duplikat Nummer i ist 1-2 Mal aufgetreten und in die i-th Position des Arrays höchstens einmal verschoben.
  • Die erste Zahl gefunden wird d auf d-ten Stellung bewegt wird, höchstens 1 Zeit
  • Die zweiten D herum höchstens N-1-mal bewegt werden und enden in m-ten Position, weil jeder anderen i- up ten Steckplatz ist besetzt mit Nummer i

  • Die second outer for lokalisieren die erste, wo ich [i]! = ich. Die einzigen i erfüllt die i = m

  • Die 2 inner fors Griff 2 Fälle, in denen m < d und m > d jeweils

vollständige Umsetzung bei http://ideone.com/VDuLka

+0

bitte die letzten beiden for loops ausarbeiten. Ich kann es nicht verstehen. –

+0

Sie haben m (= i innerhalb der 2. für) und d (= a [i]) und müssen nur die Zahlen in diesem Bereich eingeben, m -> d oder d -> m. Was würden Sie tun? –

+0

Es gibt ein falsches Ergebnis. Bitte überprüfen Sie für den Eingang 4,2,2,3,1 –

0

Nach

  int temp = arr[arr[i]-1]; 

eine Prüfung auf doppelte in der Schleife hinzu:

  if((temp-1) == i){ // found duplicate 
       ... 
      } else { 
       arr[arr[i]-1] = arr[i]; 
       arr[i] = temp; 
      } 

Sehen Sie, wenn Sie den Rest des Codes herausfinden können.

+0

Warum würde temp-1 im Falle von Duplikaten gleich i sein? –

+0

@rishavbansal - Das Problem verwendet die Zahlen 1 bis n, die Indizes sind 0 bis n-1, das heißt, nachdem die Zahlen an der richtigen Stelle sind, arr [i] = i + 1. Da temp = arr [...] ist, könnte die Überprüfung für temp == (i + 1) oder für (temp -1) == i erfolgen. Da Sie bereits nach (arr [i] -1)! = I gesucht haben, habe ich mich für eine ähnliche Prüfung entschieden. – rcgldr

1

Zuerst müssen Sie fehlende und wiederholte Nummern finden. Sie tun dies, indem folgendes Gleichungssystem gelöst:

equation

Linke Summen berechnet werden gleichzeitig durch einen Durchlauf über Array zu machen. Richtige Summen sind noch einfacher - Sie können Formeln für die arithmetische Progression verwenden, um Schleifen zu vermeiden. So, jetzt haben Sie ein System von zwei Gleichungen mit zwei Unbekannten: fehlende Nummer m und wiederholte Nummer r. Löse es.

Als nächstes "sortieren" Sie das Array, indem Sie es mit den Zahlen 1 bis n von links nach rechts ausfüllen, indem Sie m auslassen und r duplizieren. Somit erfordert der Gesamtalgorithmus nur zwei Durchgänge über das Array.

+0

Rechte Seite Summe der zweiten Gleichung = 1/3 n^3 + 1/2 n^2 + 1/6 n, die 32 Bit vorzeichenlose Ganzzahl für n> = 1626 überläuft. – rcgldr

+0

@rcgldr Es ist eine Frage der Typen für wählen die Aufgabe, nicht Algorithmen. Schön, das zu erwähnen. – Vesper

Verwandte Themen