web-dev-qa-db-ger.com

Wie verschmelzen zwei sortierte Arrays zu einem sortierten Array?

Dies wurde in einem Interview von mir verlangt und dies ist die von mir vorgeschlagene Lösung:

public static int[] merge(int[] a, int[] b) {

    int[] answer = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;
    while (i < a.length && j < b.length)
    {
        if (a[i] < b[j])
        {
            answer[k] = a[i];
            i++;
        }
        else
        {
            answer[k] = b[j];
            j++;
        }
        k++;
    }

    while (i < a.length)
    {
        answer[k] = a[i];
        i++;
        k++;
    }

    while (j < b.length)
    {
        answer[k] = b[j];
        j++;
        k++;
    }

    return answer;
}

Gibt es einen effizienteren Weg, dies zu tun? 

Bearbeiten: Längenmethode korrigiert.

154
Behrooz Karjoo

Eine kleine Verbesserung, aber nach der Hauptschleife könnten Sie System.arraycopy verwenden, um das Ende eines der Eingangsarrays zu kopieren, wenn Sie an das Ende des anderen gelangen. Das ändert jedoch nicht die O(n)-Leistungsmerkmale Ihrer Lösung.

33
Greg Hewgill
public static int[] merge(int[] a, int[] b) {

    int[] answer = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;

    while (i < a.length && j < b.length)  
       answer[k++] = a[i] < b[j] ? a[i++] :  b[j++];

    while (i < a.length)  
        answer[k++] = a[i++];


    while (j < b.length)    
        answer[k++] = b[j++];

    return answer;
}

Ist etwas kompakter aber genau das gleiche!

102
Mike Saull

Ich bin überrascht, dass niemand diese viel coolere, effizientere und kompaktere Implementierung erwähnt hat:

public static int[] merge(int[] a, int[] b) {
    int[] answer = new int[a.length + b.length];
    int i = a.length - 1, j = b.length - 1, k = answer.length;

    while (k > 0)
        answer[--k] =
                (j < 0 || (i >= 0 && a[i] >= b[j])) ? a[i--] : b[j--];
    return answer;
}

Sehenswürdigkeiten

  1. Beachten Sie, dass er dieselbe oder eine geringere Anzahl von Operationen ausführt wie jeder andere O(n) - Algorithmus, jedoch in einer einzigen Anweisung in einer einzelnen while-Schleife! 
  2. Wenn zwei Arrays ungefähr gleich groß sind, ist die Konstante für O(n) gleich. Wenn jedoch Arrays wirklich unausgewogen sind, würden Versionen mit System.arraycopy gewinnen, da dies intern mit einer einzelnen x86-Assembly-Anweisung möglich ist.
  3. Beachten Sie a[i] >= b[j] anstelle von a[i] > b[j]. Dies garantiert "Stabilität", die definiert ist, wenn Elemente von a und b gleich sind. Wir wollen Elemente von a vor b. 
54
Shital Shah

Alle Verbesserungen, die vorgenommen werden könnten, wären Mikrooptimierungen, der Gesamtalgorithmus ist korrekt.

16
ChrisH

Diese Lösung ähnelt auch anderen Beiträgen sehr, mit der Ausnahme, dass System.arrayCopy zum Kopieren der übrigen Arrayelemente verwendet wird.

private static int[] sortedArrayMerge(int a[], int b[]) {
    int result[] = new int[a.length +b.length];
    int i =0; int j = 0;int k = 0;
    while(i<a.length && j <b.length) {
        if(a[i]<b[j]) {
            result[k++] = a[i];
            i++;
        } else {
            result[k++] = b[j];
            j++;
        }
    }
    System.arraycopy(a, i, result, k, (a.length -i));
    System.arraycopy(b, j, result, k, (b.length -j));
    return result;
}
10

Hier ist die Funktion aktualisiert. Es entfernt Duplikate, hoffentlich findet jemand das brauchbar:

public static long[] merge2SortedAndRemoveDublicates(long[] a, long[] b) {
    long[] answer = new long[a.length + b.length];
    int i = 0, j = 0, k = 0;
    long tmp;
    while (i < a.length && j < b.length) {
        tmp = a[i] < b[j] ? a[i++] : b[j++];
        for ( ; i < a.length && a[i] == tmp; i++);
        for ( ; j < b.length && b[j] == tmp; j++);
        answer[k++] = tmp;
    }
    while (i < a.length) {
        tmp = a[i++];
        for ( ; i < a.length && a[i] == tmp; i++);
        answer[k++] = tmp;
    }
    while (j < b.length) {
        tmp = b[j++];
        for ( ; j < b.length && b[j] == tmp; j++);
        answer[k++] = tmp;
    }
    return Arrays.copyOf(answer, k);
}
7
vitali_y

Es kann in 4 Anweisungen wie folgt ausgeführt werden

 int a[] = {10, 20, 30};
 int b[]= {9, 14, 11};
 int res[]=new int[a.legth+b.length]; 
 System.arraycopy(a,0, res, 0, a.length); 
 System.arraycopy(b,0,res,a.length, b.length);
 Array.sort(res)

5
Sudhir

Apache-Sammlungen unterstützen die Sortiermethode seit Version 4; Sie können dies mit der collate-Methode tun in:

org.Apache.commons.collections4.CollectionUtils

Hier Zitat aus Javadoc:

collate(Iterable<? extends O> a, Iterable<? extends O> b, Comparator<? super O> c)

Führt zwei sortierte Collections, a und b, zu einem einzigen .__ zusammen. sortierte Liste so, dass die Anordnung der Elemente gemäß Vergleicher c bleibt erhalten.

Rad nicht neu erfinden! Dokumentverweis: http://commons.Apache.org/proper/commons-collections/apidocs/org/Apache/commons/collections4/CollectionUtils.html

4
Vlad

Ich musste es in Javascript schreiben, hier ist es:

function merge(a, b) {
    var result = [];
    var ai = 0;
    var bi = 0;
    while (true) {
        if ( ai < a.length && bi < b.length) {
            if (a[ai] < b[bi]) {
                result.Push(a[ai]);
                ai++;
            } else if (a[ai] > b[bi]) {
                result.Push(b[bi]);
                bi++;
            } else {
                result.Push(a[ai]);
                result.Push(b[bi]);
                ai++;
                bi++;
            }
        } else if (ai < a.length) {
            result.Push.apply(result, a.slice(ai, a.length));
            break;
        } else if (bi < b.length) {
            result.Push.apply(result, b.slice(bi, b.length));
            break;
        } else {
            break;
        }
    }
    return result;
}
3
ebdr

GallopSearch Merge: O (log (n) * log (i)) statt O (n)

Ich ging weiter und setzte den Greybeard-Vorschlag in den Kommentaren um. Meistens, weil ich eine äußerst effiziente missionskritische Version dieses Codes brauchte.

  • Der Code verwendet eine GallopSearch, die O(log(i)) ist, wobei i der Abstand vom aktuellen Index ist, in dem der relevante Index vorhanden ist.
  • Der Code verwendet eine binäre Suche, nachdem die Galopp-Suche den richtigen Bereich identifiziert hat. Da der Galopp dies auf einen kleineren -Bereich beschränkt hat, ist die resultierende binarySearch auch O (log (i)).
  • Der Galopp und das Zusammenführen werden rückwärts ausgeführt. Dies scheint nicht missionskritisch zu sein, erlaubt jedoch das Zusammenführen von Arrays. Wenn eines Ihrer Arrays über ausreichend Speicherplatz für die Ergebniswerte verfügt, können Sie es einfach als zusammenführendes Array und das Ergebnisarray verwenden. In diesem Fall müssen Sie den gültigen Bereich innerhalb des Arrays angeben.
  • In diesem Fall ist keine Speicherzuweisung erforderlich (große Einsparungen bei kritischen Vorgängen). Es stellt einfach sicher, dass es keine unverarbeiteten Werte überschreibt (und dies nicht rückgängig gemacht werden kann). Tatsächlich verwenden Sie dasselbe Array für die Eingaben und die Ergebnisse. Es wird keine negativen Auswirkungen haben.
  • Ich habe konsequent Integer.compare () verwendet, um dies für andere Zwecke auszuschalten.
  • Es besteht die Möglichkeit, dass ich ein bisschen vermasselt und Informationen, die ich zuvor bewiesen habe, nicht verwendet hat. B. die binäre Suche in einem Bereich von zwei Werten, für die bereits ein Wert geprüft wurde. Möglicherweise gibt es auch eine bessere Möglichkeit, die Hauptschleife anzugeben. Der umkehrende c-Wert wäre nicht erforderlich, wenn sie in zwei aufeinander folgenden Operationen kombiniert würden. Da Sie wissen, werden Sie jedes Mal eins zum anderen tun. Es gibt Platz für etwas Politur.

Dies sollte der effizienteste Weg sein, dies mit der zeitlichen Komplexität von O (log (n) * log (i)) anstelle von O (n) zu tun. Und im ungünstigsten Fall die Komplexität von O (n). Wenn Ihre Arrays klumpig sind und lange Wertebereiche enthalten, wird dies auf jede andere Art und Weise in den Schatten gestellt, ansonsten ist es einfach besser als sie.

Es hat zwei Lesewerte an den Enden des zusammenführenden Arrays und den Schreibwert innerhalb des Ergebnisarrays. Nachdem Sie herausgefunden haben, welcher Endwert niedriger ist, führt er eine Galopp-Suche in diesem Array durch. 1, 2, 4, 8, 16, 32 usw. Wenn der Bereich ermittelt wird, in dem der gelesene Wert des anderen Arrays größer ist. Es sucht binär in diesen Bereich (halbiert den Bereich, sucht die richtige Hälfte, wiederholt sich bis zu einem einzelnen Wert). Dann kopiert das Array diese Werte in die Schreibposition. Beachten Sie, dass die Kopie notwendigerweise so verschoben wird, dass sie nicht dieselben Werte aus den beiden lesenden Arrays überschreiben kann (was bedeutet, dass das Schreibarray und das Lesearray gleich sein können). Dann führt er dieselbe Operation für das andere Array durch, von dem jetzt bekannt ist, dass es unter dem neuen Lesewert des anderen Arrays liegt.

static public int gallopSearch(int current, int[] array, int v) {
    int d = 1;
    int seek = current - d;
    int prevIteration = seek;
    while (seek > 0) {
        if (Integer.compare(array[seek], v) <= 0) {
            break;
        }
        prevIteration = seek;
        d <<= 1;
        seek = current - d;
        if (seek < 0) {
            seek = 0;
        }
    }
    if (prevIteration != seek) {
        seek = binarySearch(array, seek, prevIteration, v);
        seek = seek >= 0 ? seek : ~seek;
    }
    return seek;
}

static public int binarySearch(int[] list, int fromIndex, int toIndex, int v) {
    int low = fromIndex;
    int high = toIndex - 1;
    while (low <= high) {
        int mid = (low + high) >>> 1;
        int midVal = list[mid];
        int cmp = Integer.compare(midVal, v);
        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            return mid;// key found
        }
    }
    return -(low + 1);// key not found.
}

static public int[] sortedArrayMerge(int[] a, int[] b) {
    return sortedArrayMerge(null, a, a.length, b, b.length);
}

static public int[] sortedArrayMerge(int[] results, int[] a, int aRead, int b[], int bRead) {
    int write = aRead + bRead, length, gallopPos;
    if ((results == null) || (results.length < write)) {
        results = new int[write];
    }
    if (aRead > 0 && bRead > 0) {
        int c = Integer.compare(a[aRead - 1], b[bRead - 1]);
        while (aRead > 0 && bRead > 0) {
            switch (c) {
                default:
                    gallopPos = gallopSearch(aRead, a, b[bRead-1]);
                    length = (aRead - gallopPos);
                    write -= length;
                    aRead = gallopPos;
                    System.arraycopy(a, gallopPos--, results, write, length);
                    c = -1;
                    break;
                case -1:
                    gallopPos = gallopSearch(bRead, b, a[aRead-1]);
                    length = (bRead - gallopPos);
                    write -= length;
                    bRead = gallopPos;
                    System.arraycopy(b, gallopPos--, results, write, length);
                    c = 1;
                    break;
            }
        }
    }
    if (bRead > 0) {
        if (b != results) {
            System.arraycopy(b, 0, results, 0, bRead);
        }
    } else if (aRead > 0) {
        if (a != results) {
            System.arraycopy(a, 0, results, 0, aRead);
        }
    }
    return results;
}

Dies sollte der effizienteste Weg sein.


Einige Antworten hatten eine doppelte Fähigkeit zum Entfernen. Dies erfordert einen O(n) - Algorithmus, da Sie jedes Element tatsächlich vergleichen müssen. Hier ist also ein Stand-Alone-Verfahren, das im Nachhinein angewendet werden kann. Sie können nicht durch mehrere Einträge hindurch galoppieren, wenn Sie alle ansehen müssen, obwohl Sie durch die Duplikate galoppieren könnten, wenn Sie viele davon hätten.

static public int removeDuplicates(int[] list, int size) {
    int write = 1;
    for (int read = 1; read < size; read++) {
        if (list[read] == list[read - 1]) {
            continue;
        }
        list[write++] = list[read];
    }
    return write;
}

Update: Vorherige Antwort, kein schrecklicher Code, aber deutlich unterlegen.

Eine weitere unnötige Hyperoptimierung. Es ruft nicht nur arraycopy für die Endbits auf, sondern auch für den Anfang. Bearbeitung aller einleitenden Nichtüberlappungen in O(log(n)) durch eine binäre Suche in den Daten. O(log(n) + n) ist O(n) und in einigen Fällen wird der Effekt ziemlich ausgeprägt sein, insbesondere wenn sich überhaupt keine Überschneidungen zwischen den zusammengeführten Arrays ergeben.

private static int binarySearch(int[] array, int low, int high, int v) {
    high = high - 1;
    while (low <= high) {
        int mid = (low + high) >>> 1;
        int midVal = array[mid];
        if (midVal > v)
            low = mid + 1;
        else if (midVal < v)
            high = mid - 1;
        else
            return mid; // key found
    }
    return low;//traditionally, -(low + 1);  // key not found.
}

private static int[] sortedArrayMerge(int a[], int b[]) {
    int result[] = new int[a.length + b.length];
    int k, i = 0, j = 0;
    if (a[0] > b[0]) {
        k = i = binarySearch(b, 0, b.length, a[0]);
        System.arraycopy(b, 0, result, 0, i);
    } else {
        k = j = binarySearch(a, 0, a.length, b[0]);
        System.arraycopy(a, 0, result, 0, j);
    }
    while (i < a.length && j < b.length) {
        result[k++] = (a[i] < b[j]) ? a[i++] : b[j++];
    }
    if (j < b.length) {
        System.arraycopy(b, j, result, k, (b.length - j));
    } else {
        System.arraycopy(a, i, result, k, (a.length - i));
    }
    return result;
}
2
Tatarize

Hier ist eine verkürzte, in Javascript geschriebene Form:

function sort( a1, a2 ) {

    var i = 0
        , j = 0
        , l1 = a1.length
        , l2 = a2.length
        , a = [];

    while( i < l1 && j < l2 ) {

        a1[i] < a2[j] ? (a.Push(a1[i]), i++) : (a.Push( a2[j]), j++);
    }

    i < l1 && ( a = a.concat( a1.splice(i) ));
    j < l2 && ( a = a.concat( a2.splice(j) ));

    return a;
}
2
swallace

Der Algorithmus kann auf viele Arten verbessert werden. Zum Beispiel ist es sinnvoll zu prüfen, ob a[m-1]<b[0] oder b[n-1]<a[0]. In keinem dieser Fälle müssen mehr Vergleiche angestellt werden. Der Algorithmus könnte nur Quellarrays in der resultierenden in der richtigen Reihenfolge kopieren.

Kompliziertere Verbesserungen können das Suchen nach verschachtelten Teilen umfassen und den Zusammenführungsalgorithmus nur für diese ausführen. Es könnte viel Zeit gespart werden, wenn die Größen der zusammengeführten Arrays sich in Punktzahlen unterscheiden.

1
Hengameh
public static int[] merge(int[] a, int[] b) {
    int[] mergedArray = new int[(a.length + b.length)];
    int i = 0, j = 0;
    int mergedArrayIndex = 0;
    for (; i < a.length || j < b.length;) {
        if (i < a.length && j < b.length) {
            if (a[i] < b[j]) {
                mergedArray[mergedArrayIndex] = a[i];
                i++;
            } else {
                mergedArray[mergedArrayIndex] = b[j];
                j++;
            }
        } else if (i < a.length) {
            mergedArray[mergedArrayIndex] = a[i];
            i++;
        } else if (j < b.length) {
            mergedArray[mergedArrayIndex] = b[j];
            j++;
        }
        mergedArrayIndex++;
    }
    return mergedArray;
}
1
toobsco42

Dieses Problem hängt mit dem Mergesort-Algorithmus zusammen, bei dem zwei sortierte Subarrays zu einem einzigen sortierten Subarray zusammengefasst werden. Das Buch " CLRS " gibt ein Beispiel für den Algorithmus und beseitigt die Notwendigkeit, zu prüfen, ob das Ende erreicht wurde, indem am Ende von ein Sentinel-Wert (etwas Vergleichbares und "größer als jeder andere Wert") hinzugefügt wird jedes Array.

Ich habe dies in Python geschrieben, sollte sich aber auch gut in Java übersetzen lassen:

def func(a, b):
    class sentinel(object):
        def __lt__(*_):
            return False

    ax, bx, c = a[:] + [sentinel()], b[:] + [sentinel()], []
    i, j = 0, 0

    for k in range(len(a) + len(b)):
        if ax[i] < bx[j]:
            c.append(ax[i])
            i += 1
        else:
            c.append(bx[j])
            j += 1

    return c
1
d11wtq

Sie können 2 Threads verwenden, um das resultierende Array zu füllen, einen von vorne, einen von hinten.

Dies kann ohne jegliche Synchronisation bei Zahlen funktionieren, z. wenn jeder Thread die Hälfte der Werte einfügt.

1
tkruse

Ich denke, die Einführung der Übersprungsliste für das größere sortierte Array kann die Anzahl der Vergleiche reduzieren und den Kopiervorgang in das dritte Array beschleunigen. Dies kann gut sein, wenn das Array zu groß ist.

1
sriragav
    public class Merge {

    // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
    public static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {

        // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
        assert isSorted(a, lo, mid);
        assert isSorted(a, mid+1, hi);

        // copy to aux[]
        for (int k = lo; k <= hi; k++) {
            aux[k] = a[k]; 
        }

        // merge back to a[]
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)              a[k] = aux[j++];
            else if (j > hi)               a[k] = aux[i++];
            else if (less(aux[j], aux[i])) a[k] = aux[j++];
            else                           a[k] = aux[i++];
        }

        // postcondition: a[lo .. hi] is sorted
        assert isSorted(a, lo, hi);
    }

    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
    private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, aux, lo, mid);
        sort(a, aux, mid + 1, hi);
        merge(a, aux, lo, mid, hi);
    }

    public static void sort(Comparable[] a) {
        Comparable[] aux = new Comparable[a.length];
        sort(a, aux, 0, a.length-1);
        assert isSorted(a);
    }


   /***********************************************************************
    *  Helper sorting functions
    ***********************************************************************/

    // is v < w ?
    private static boolean less(Comparable v, Comparable w) {
        return (v.compareTo(w) < 0);
    }

    // exchange a[i] and a[j]
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }


   /***********************************************************************
    *  Check if array is sorted - useful for debugging
    ***********************************************************************/
    private static boolean isSorted(Comparable[] a) {
        return isSorted(a, 0, a.length - 1);
    }

    private static boolean isSorted(Comparable[] a, int lo, int hi) {
        for (int i = lo + 1; i <= hi; i++)
            if (less(a[i], a[i-1])) return false;
        return true;
    }


   /***********************************************************************
    *  Index mergesort
    ***********************************************************************/
    // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
    private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) {

        // copy to aux[]
        for (int k = lo; k <= hi; k++) {
            aux[k] = index[k]; 
        }

        // merge back to a[]
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)                    index[k] = aux[j++];
            else if (j > hi)                     index[k] = aux[i++];
            else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++];
            else                                 index[k] = aux[i++];
        }
    }

    // return a permutation that gives the elements in a[] in ascending order
    // do not change the original array a[]
    public static int[] indexSort(Comparable[] a) {
        int N = a.length;
        int[] index = new int[N];
        for (int i = 0; i < N; i++)
            index[i] = i;

        int[] aux = new int[N];
        sort(a, index, aux, 0, N-1);
        return index;
    }

    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
    private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, index, aux, lo, mid);
        sort(a, index, aux, mid + 1, hi);
        merge(a, index, aux, lo, mid, hi);
    }

    // print array to standard output
    private static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            StdOut.println(a[i]);
        }
    }

    // Read strings from standard input, sort them, and print.
    public static void main(String[] args) {
        String[] a = StdIn.readStrings();
        Merge.sort(a);
        show(a);
    }
}
1
jackhao
public int[] merge(int[] a, int[] b) {
    int[] result = new int[a.length + b.length];
    int aIndex, bIndex = 0;

    for (int i = 0; i < result.length; i++) {
        if (aIndex < a.length && bIndex < b.length) {
            if (a[aIndex] < b[bIndex]) {
                result[i] = a[aIndex];
                aIndex++;
            } else {
                result[i] = b[bIndex];
                bIndex++;
            }
        } else if (aIndex < a.length) {
            result[i] = a[aIndex];
            aIndex++;
        } else {
            result[i] = b[bIndex];
            bIndex++;
        }
    }

    return result;
}
1
Andrew
//How to merge two sorted arrays into a sorted array without duplicates?
//simple C Coding
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main()
{
    int InputArray1[] ={1,4,5,7,8,9,12,13,14,17,40};
    int InputArray2[] ={4,5,11,14,15,17,18,19,112,122,122,122,122};
    int n=10;
    int OutputArray[30];
    int i=0,j=0,k=0;
    //k=OutputArray
    while(i<11 && j<13)
    {
        if(InputArray1[i]<InputArray2[j])
        {
            if (k == 0 || InputArray1[i]!= OutputArray[k-1])
            {
                OutputArray[k++] = InputArray1[i];
            }
            i=i+1;
        }
        else if(InputArray1[i]>InputArray2[j])
        {
            if (k == 0 || InputArray2[j]!= OutputArray[k-1])
            {
                OutputArray[k++] = InputArray2[j];
            }
            j=j+1;
        }
        else
        {
            if (k == 0 || InputArray1[i]!= OutputArray[k-1])
            {
                OutputArray[k++] = InputArray1[i];
            }
            i=i+1;
            j=j+1;
        }
    };
    while(i<11)
    {
        if(InputArray1[i]!= OutputArray[k-1])
            OutputArray[k++] = InputArray1[i++];
        else
            i++;
    }
    while(j<13)
    {
        if(InputArray2[j]!= OutputArray[k-1])
            OutputArray[k++] = InputArray2[j++];
        else
            j++;
    }
    for(i=0; i<k; i++)
    {
        printf("sorted data:%d\n",OutputArray[i]);
    };
}
0
Chanchal
var arrCombo = function(arr1, arr2){
  return arr1.concat(arr2).sort(function(x, y) {
    return x - y;
  });
};
0
Alex Hawkins

Um zwei sortierte Arrays in der Zeitkomplexität O (m + n) zu margen, verwenden Sie unterhalb des Ansatzes nur eine Schleife. _. M und n ist die Länge des ersten Arrays und des zweiten Arrays.

public class MargeSortedArray {
    public static void main(String[] args) {
        int[] array = new int[]{1,3,4,7};
        int[] array2 = new int[]{2,5,6,8,12,45};
        int[] newarry = margeToSortedArray(array, array2);
        //newarray is marged array
    }

    // marge two sorted array with o(a+n) time complexity
    public static int[] margeToSortedArray(int[] array, int[] array2) {
        int newarrlen = array.length+array2.length;
        int[] newarr = new int[newarrlen];

        int pos1=0,pos2=0;
        int len1=array.length, len2=array2.length;

        for(int i =0;i<newarrlen;i++) {     
            if(pos1>=len1) {
                newarr[i]=array2[pos2];
                pos2++;
                continue;
            }
            if(pos2>=len2) {
                newarr[i]=array[pos1];
                pos1++;
                continue;
            }

            if(array[pos1]>array2[pos2]) {
                newarr[i]=array2[pos2];
                pos2++;
            } else {
                newarr[i]=array[pos1];
                pos1++;
            }   
        }

        return newarr;
    }

}
0
Birbal Singh
public static int[] merge(int[] listA, int[] listB) {
        int[] mergedList = new int[ listA.length + listB.length];
        int i = 0; // Counter for listA
        int j = 0; // Counter for listB
        int k = 0; // Counter for mergedList
        while (true) {
            if (i >= listA.length && j >= listB.length) {
                break;
            }
            if (i < listA.length && j < listB.length) { // If both counters are valid.
                if (listA[i] <= listB[j]) {
                    mergedList[k] = listA[i];
                    k++;
                    i++;
                } else {
                    mergedList[k] = listB[j];
                    k++;
                    j++;
                }
            } else if (i < listA.length && j >= listB.length) { // If only A's counter is valid.
                mergedList[k] = listA[i];
                k++;
                i++;
            } else if (i <= listA.length && j < listB.length) { // If only B's counter is valid
                mergedList[k] = listB[j];
                k++;
                j++;
            }
        }
        return mergedList;
    }
0
Sean Woolfolk
public static int[] mergeSorted(int[] left, int[] right) {
    System.out.println("merging " + Arrays.toString(left) + " and " + Arrays.toString(right));
    int[] merged = new int[left.length + right.length];
    int nextIndexLeft = 0;
    int nextIndexRight = 0;
    for (int i = 0; i < merged.length; i++) {
        if (nextIndexLeft >= left.length) {
            System.arraycopy(right, nextIndexRight, merged, i, right.length - nextIndexRight);
            break;
        }
        if (nextIndexRight >= right.length) {
            System.arraycopy(left, nextIndexLeft, merged, i, left.length - nextIndexLeft);
            break;
        }
        if (left[nextIndexLeft] <= right[nextIndexRight]) {
            merged[i] = left[nextIndexLeft];
            nextIndexLeft++;
            continue;
        }
        if (left[nextIndexLeft] > right[nextIndexRight]) {
            merged[i] = right[nextIndexRight];
            nextIndexRight++;
            continue;
        }
    }
    System.out.println("merged : " + Arrays.toString(merged));
    return merged;
}

Nur ein kleiner Unterschied zur ursprünglichen Lösung

0

Meine bevorzugte Programmiersprache ist JavaScript

function mergeSortedArrays(a, b){
    var result = [];

    var sI = 0;
    var lI = 0;
    var smallArr;
    var largeArr;
    var temp;

    if(typeof b[0] === 'undefined' || a[0]<b[0]){
        smallArr = a;
        largeArr = b;
    } else{
        smallArr = b;
        largeArr = a;
    }

    while(typeof smallArr[sI] !== 'undefined'){
        result.Push(smallArr[sI]);
        sI++;

        if(smallArr[sI]>largeArr[lI] || typeof smallArr[sI] === 'undefined'){
            temp = smallArr;
            smallArr = largeArr;
            largeArr = temp;
            temp = sI;
            sI = lI;
            lI = temp;
        }
    }
    return result;
}
0
Saad Ahmed

Sie können ternäre Operatoren verwenden, um den Code etwas kompakter zu gestalten

public static int[] mergeArrays(int[] a1, int[] a2) {
    int[] res = new int[a1.length + a2.length];
    int i = 0, j = 0;

    while (i < a1.length && j < a2.length) {
        res[i + j] = a1[i] < a2[j] ? a1[i++] : a2[j++];
    }

    while (i < a1.length) {
        res[i + j] = a1[i++];
    }

    while (j < a2.length) {
        res[i + j] = a2[j++];
    }

    return res;
}
0
Jenna Kwon
var arr1 = [2,10,20,30,100];
var arr2 = [2,4,5,6,7,8,9];
var j = 0;
var i =0;
var newArray = [];

for(var x=0;x< (arr1.length + arr2.length);x++){
    if(arr1[i] >= arr2[j]){                //check if element arr2 is equal and less than arr1 element
        newArray.Push(arr2[j]);
      j++;
    }else if(arr1[i] < arr2[j]){            //check if element arr1 index value  is less than arr2 element
        newArray.Push(arr1[i]);
        i++;
    }
    else if(i == arr1.length || j < arr2.length){    // add remaining arr2 element
        newArray.Push(arr2[j]);
        j++
    }else{                                                   // add remaining arr1 element
        newArray.Push(arr1[i]); 
        i++
    }

}

console.log(newArray);
0
Amar1990
public static void main(String[] args) {
    int[] arr1 = {2,4,6,8,10,999};
    int[] arr2 = {1,3,5,9,100,1001};

    int[] arr3 = new int[arr1.length + arr2.length];

    int temp = 0;

    for (int i = 0; i < (arr3.length); i++) {
        if(temp == arr2.length){
            arr3[i] = arr1[i-temp];
        }
        else if (((i-temp)<(arr1.length)) && (arr1[i-temp] < arr2[temp])){
                arr3[i] = arr1[i-temp];
        }
        else{
            arr3[i] = arr2[temp];
            temp++;
        }
    }

    for (int i : arr3) {
        System.out.print(i + ", ");
    }
}

Ausgabe ist:

1, 2, 3, 4, 5, 6, 8, 9, 10, 100, 999, 1001 

0
Rajesh Gurbani

Verwenden Sie möglicherweise System.arraycopy

public static byte[] merge(byte[] first, byte[] second){
    int len = first.length + second.length;
    byte[] full = new byte[len];
    System.arraycopy(first, 0, full, 0, first.length);
    System.arraycopy(second, 0, full, first.length, second.length);
    return full;
}
0
nurisezgin