Maximum Subarray: Teile und herrsche

Disclaimer: dies ist für eine Zuordnung. Ich bin nicht zu Fragen, für die explizit programmiert werden, es müssen nur genug helfen zu verstehen, die der Algorithmus beteiligt, so dass ich vielleicht beheben Sie die Fehler in meinem code.

Okay, also du bist wahrscheinlich vertraut mit der maximum-subarray problem: Berechnung und Rückgabe der größte zusammenhängende block von ganzen zahlen in einem array. Einfach genug, aber diese Zuordnung verlangt von mir zu tun es in drei verschiedenen Komplexitäten: O(n^3), O(n^2) und O(n log n). Ich habe die ersten beiden ohne viel Mühe (brute force) aber die Dritte gibt mir Kopfschmerzen ... buchstäblich.

Ich verstehen, wie der Algorithmus funktionieren soll: ein array an eine Funktion übergeben, teilt es in zwei Hälften rekursiv, vergleicht dann die einzelnen Komponenten zu finden, die maximale subarray in jeder Hälfte. Dann, da die maximale subarray muss, befindet sich ganz in der linken oder rechten Hälfte, oder in einem segment überlappen die beiden, Sie müssen das maximale subarray, die überlappungen Links und rechts. Vergleichen Sie die max subarrays für jeden Fall, und die größte wird Ihren Wert zurückgeben.

Ich glaube, ich habe code geschrieben, der führt, der Aufgabe angemessen, aber ich scheine falsch zu sein in der Bewertung. Ich habe versucht, an den Lehrer und TA für die Hilfe, aber ich habe nicht das Gefühl, dass ich immer überall mit, entweder von Ihnen. Unten ist der code hab ich es geschafft zu schreiben so weit. Bitte sagen Sie mir, wenn Sie irgendwelche eklatante Fehler. Nochmal, ich bin nicht auf der Suche nach expliziten code oder Antworten, aber helfen, zu verstehen, was ich falsch mache. Ich habe gesucht durch alle ähnliche Fälle hier vorgestellt und habe nicht gefunden was kann mir wirklich helfen. Habe ich auch getan, viele der Google-Suche nach Orientierung, aber auch das hilft nicht viel, entweder. Wie auch immer, hier ist der code in Frage:

int conquer(int arr[], int first, int mid, int last) {

    int i = 0;
    int maxLeft = 0;
    int maxRight = 0;

    int temp = 0;
    for (i = mid; i >= first; i--) {
        temp = temp + arr[i];
        if (maxLeft < temp) {
            maxLeft = temp;
        }
    }
    temp = 0;
    for (i = (mid + 1); i <= last; i++) {
        temp = temp + arr[i];
        if (maxRight < temp) {
            maxRight = temp;
        }
    }

    return (maxLeft + maxRight);
}

int divide(int arr[], int start, int end) {

    int i;
    int maxSum;
    int maxLeftSum;
    int maxRightSum;
    int maxOverlapSum;

    if (start == end) {
        return arr[start];
    } else {
        int first = start;
        int mid = (end / 2);
        int last = end;

        maxSum = 0;
        maxLeftSum = 0;

        for (i = first; i < mid; i++) {
            maxSum = maxSum + arr[i];
            if (maxLeftSum < maxSum) {
                maxLeftSum = maxSum;
            }
        }
        for (i = (mid + 1); i < last; i++) {
            maxSum = maxSum + arr[i];
            if (maxRightSum < maxSum) {
                maxRightSum = maxSum;
            }
        }

        maxOverlapSum = conquer(arr, first, mid, last);
    }

    if ((maxLeftSum > maxRightSum) && (maxLeftSum > maxOverlapSum)) {
        return maxLeftSum;
    } else if ((maxRightSum > maxLeftSum) && (maxRightSum > maxOverlapSum)) {
        return maxRightSum;
    } else
        return maxOverlapSum;
}

Edit: die Fehler, die ich bin immer ein Falsches Ergebnis. Ich habe konsistente und korrekte Ergebnisse zwischen meine beiden anderen algorithmen, aber das ist falsch.

Edit #2: Hier ist eine aktualisierte version von meinem code abgespeckt ein bisschen und ich wurden ein paar Dinge. Es ist immer noch nicht korrekt läuft, sollte es doch viel näher...

#include <stdio.h>
#include <stdlib.h>

int numarr[] = {22, -27, 38, -34, 49, 40, 13, -44, -13, 28, 46, 7, -26, 42,
        29, 0, -6, 35, 23, -37, 10, 12, -2, 18, -12, -49, -10, 37, -5, 17,
        6, -11, -22, -17, -50, -40, 44, 14, -41, 19, -15, 45, -23, 48, -1,
        -39, -46, 15, 3, -32, -29, -48, -19, 27, -33, -8, 11, 21, -43, 24,
        5, 34, -36, -9, 16, -31, -7, -24, -47, -14, -16, -18, 39, -30, 33,
        -45, -38, 41, -3, 4, -25, 20, -35, 32, 26, 47, 2, -4, 8, 9, 31, -28,
        36, 1, -21, 30, 43, 25, -20, -42};

int length = ((sizeof(numarr))/(sizeof(int)));

int divide(int left, int right) {

    int mid, i, temp, mLeft, mRight, mCross = 0;

    if (left == right) {
        return left;
    } else if (left > right) {
        return 0;
    } else {
        mid = (left + right) / 2;

        divide(left, mid);
        divide(mid + 1, right);

        for (i = mid; i >= left; i--) {
            temp = temp + numarr[i];
            if (mLeft < temp) {
                mLeft = temp;
            }
        }

        for (i = mid + 1; i <= right; i++) {
            temp = temp + numarr[i];
            if (mRight < temp) {
                mRight = temp;
            }
        }

        mCross = (mLeft + mRight);

        printf("mLeft:  %d\n", mLeft);
        printf("mRight: %d\n", mRight);
        printf("mCross: %d\n", mCross);

        return 0;
    }
}

int main(int argc, char const *argv[])
{
    divide(0, length);
    return 0;
}
  • Ich wünschte, ich hatte Zeit, diese zu beantworten, aber ich bin zu begeben Sie sich auf eine Stunde+ pendeln. Ich musste nur erwähnen, das ist einfach einer der schönsten vorgestellt Hausaufgaben Aufgaben, die ich gesehen habe, auf SO eine lange Zeit. Oh, und im Gegensatz zu den meisten Studenten, Ihre code-Formatierung, Namensgebung, etc, ist pro. Seine lesbar, ohne Kommentare, das sagt viel. Viel Glück.
  • Sie implementieren müssen, um die Kluft Schritt. Ihre aktuelle Implementierung nur berechnet die überschneidung Summe für die Letzte iteration, so verpassen Sie die überlappung Summen der kleinere sub-arrays.
  • Ich gehe davon aus, dass Sie Ihnen eine Antwort, wenn das so ist, bin ich gespannt, was Sie behaupten es ist. Es würde helfen zu wissen, wenn dein Algorithmus wird schließlich auf allen Zylindern.
  • Ich weiß nicht, ob Sie, aber ich werde Sie wissen lassen, wenn ich es herausfinden. Ich bin fast sicher, ich habe den Algorithmus jetzt, so ist es nur eine Frage der Reinigung meiner Umsetzung, um es arbeiten ordnungsgemäß. Ich bin in der Nähe, dass, obwohl!
  • Ich habe 223 für die Antwort, aber die Anzeige der partition, wenn kam, ist... anstrengenderen =P
  • Ich glaube, die Antwort ist 239. Mein Lehrer gab uns verschiedene sets testen Sie unsere algorithmen, und die Antworten, damit wir wissen würden, wenn Sie richtig umgesetzt werden. Meine anderen algorithmen berechnet 239 auch so bin ich sehr sicher, dass seine Antwort richtig ist. Die neueste version dieser Implementierung ist, mich immer zu 254, also bin ich wirklich in der Nähe...
  • sind Sie richtig. Es ist in der Tat, 239. Ich hatte einen Fehler in meiner Links-Kreuzung Schleife, die sich bewegte von 0..mid-1 eher als Mitte-1..0 ich gepostet habe hier eine Antwort wenn Sie interessiert sind, es zu sehen. Es basierte ursprünglich auf dem code. Es wird deutlich anders als dein code, dass ich den 0-basierten array mit jeder partition wie ich es beschrieben kurz in meiner Antwort weiter unten (siehe midsplit() Probe). Ich auch pass basiert offset können Sie sehen, welche partition ergab die Summen. Vielen Dank für den Spaß, sir. kewl, problem, code für.
  • Einfach nur neugierig; könnten Sie bitte die O(n^2) und O(n^3) Ansatz-code?

InformationsquelleAutor idigyourpast | 2013-02-01
Schreibe einen Kommentar