Optimieren Sie die Sortierung mit "Sub-Vektor-Umkehrungen"

23

Dies ist eine Herausforderung mit den , bei der das Ziel darin besteht, einen Vektor mit den wenigsten Umkehrungen in aufsteigender Reihenfolge zu sortieren. Ihr Algorithmus kann den Vektor nur mit "Subvektorumkehrungen" 1 sortieren , aber er kann andere Operationen für arithmetische Operationen, Schleifen, zum Überprüfen, ob er sortiert ist usw. verwenden. Die Anzahl der Subvektorumkehrungen, die Ihr Algorithmus durchführt, ist seine Punktzahl.


1 Eine "Subvektorumkehr":

  • Wählen Sie einen Zahlenbereich im Vektor aus und kehren Sie die Elemente in diesem Bereich um.

Um ein einfaches Beispiel zu geben: Wenn Sie mit dem Vektor beginnen {4,3,2,1}, können Sie ihn auf viele verschiedene Arten sortieren:

  1. Kehrt den gesamten Vektor um. Dies ist offensichtlich der kürzeste Ansatz, da nur eine Umkehrung erforderlich ist:{4,3,2,1} -> {1,2,3,4}
  2. Sie können eine Version der Blasensortierung ausführen, für die 6 Umkehrungen erforderlich sind: {4,3,2,1} -> {3,4,2,1} -> {3,2,4,1} -> {2,3,4,1} -> {2,3,1,4} -> {2,1,3,4} -> {1,2,3,4}
  3. Sie können mit den ersten drei Elementen beginnen, dann mit den drei letzten und schließlich mit den beiden ersten und den beiden letzten, was 4 Tauschvorgänge erfordert: {4,3,2,1} -> {2,3,4,1} -> {2,1,4,3} -> {1,2,4,3} -> {1,2,3,4}
  4. ... und so weiter. Es stehen unendlich viele Optionen zur Verfügung (Sie können jeden Vorgang wiederholen, wenn Sie möchten).

Regeln und Anforderungen:

  • Bei einer Liste mit 100 Nummern muss Ihr Code in weniger als einer Minute fertig sein. Sie können dies selbst zeitlich festlegen, aber spielen Sie bitte fair 2 .

  • Sie müssen die Start- und Endindizes aller von Ihnen durchgeführten Swaps speichern, damit die Lösung überprüft werden kann. (Was dies bedeutet, erkläre ich weiter unten).

  • Der Code muss deterministisch sein.

  • Sie können die Eingabe in jedem gewünschten Format vornehmen: Numerischer Vektor, verknüpfte Liste, Array mit Länge ... nach Belieben.

  • Sie können eine Kopie des Vektors nach Belieben bearbeiten. Dazu gehört es, verschiedene Stornierungen vorzunehmen und zu prüfen, welche am effizientesten ist. Brute-Forcing ist völlig in Ordnung, aber halten Sie sich an das Zeitlimit.

  • Die Punktzahl ist die Gesamtzahl der Flips für die 5 Testvektoren. Tie-Breaker wird der Datumsstempel.


Beispiel:

4 1 23 21 49 2 7 9 2 | Anfangsvektor / Liste
4 1 2 9 7 2 49 21 23 | (2, 8) (Elemente zwischen den Indizes 2 und 8 umgedreht)
4 1 2 2 7 9 49 21 23 | (3, 5)
4 1 2 2 7 9 23 21 49 | (6, 8)
4 1 2 2 7 9 21 23 49 | (6, 7)
 2 2 1 4 7 9 21 23 49 | (0, 3)
 1 2 2 4 7 9 21 23 49 | (0, 2)

Die Punktzahl wäre 6, da Sie 6 Umkehrungen durchgeführt haben. Sie müssen die auf der rechten Seite aufgelisteten Indizes in einem geeigneten Format speichern (nicht drucken), das zu Überprüfungszwecken leicht gedruckt / ausgegeben werden kann.

Testvektoren:

133, 319, 80, 70, 194, 333, 65, 21, 345, 142, 82, 491, 92, 167, 281, 386, 48, 101, 394, 130, 111, 139, 214, 337, 180, 24, 443, 35, 376, 13, 166, 59, 452, 429, 406, 256, 133, 435, 446, 304, 350, 364, 447, 471, 236, 177, 317, 342, 294, 146, 280, 32, 135, 399, 78, 251, 467, 305, 366, 309, 162, 473, 27, 67, 305, 497, 112, 399, 103, 178, 386, 343, 33, 134, 480, 147, 466, 244, 370, 140, 227, 292, 28, 357, 156, 367, 157, 60, 214, 280, 153, 445, 301, 108, 77, 404, 496, 3, 226, 37

468, 494, 294, 42, 19, 23, 201, 47, 165, 118, 414, 371, 163, 430, 295, 333, 147, 336, 403, 490, 370, 128, 261, 91, 173, 339, 40, 54, 331, 236, 255, 33, 237, 272, 193, 91, 232, 452, 79, 435, 160, 328, 47, 179, 162, 239, 315, 73, 160, 266, 83, 451, 317, 255, 491, 70, 18, 275, 339, 298, 117, 145, 17, 178, 232, 59, 109, 271, 301, 437, 63, 103, 130, 15, 265, 281, 365, 444, 180, 257, 99, 248, 378, 158, 210, 466, 404, 263, 29, 117, 417, 357, 44, 495, 303, 428, 146, 215, 164, 99

132, 167, 361, 145, 36, 56, 343, 330, 14, 412, 345, 263, 306, 462, 101, 453, 364, 389, 432, 32, 200, 76, 268, 291, 35, 13, 448, 188, 11, 235, 184, 439, 175, 159, 360, 46, 193, 440, 334, 128, 346, 192, 263, 466, 175, 407, 340, 393, 231, 472, 122, 254, 451, 485, 257, 67, 200, 135, 132, 421, 205, 398, 251, 286, 292, 488, 480, 56, 284, 484, 157, 264, 459, 6, 289, 311, 116, 138, 92, 21, 307, 172, 352, 199, 55, 38, 427, 214, 233, 404, 330, 105, 223, 495, 334, 169, 168, 444, 268, 248

367, 334, 296, 59, 18, 193, 118, 10, 276, 180, 242, 115, 233, 40, 225, 244, 147, 439, 297, 115, 354, 248, 89, 423, 47, 458, 64, 33, 463, 142, 5, 13, 89, 282, 186, 12, 70, 289, 385, 289, 274, 136, 39, 424, 174, 186, 489, 73, 296, 39, 445, 308, 451, 384, 451, 446, 282, 419, 479, 220, 35, 419, 161, 14, 42, 321, 202, 30, 32, 162, 444, 215, 218, 102, 140, 473, 500, 480, 402, 1, 1, 79, 50, 54, 111, 189, 147, 352, 61, 460, 196, 77, 315, 304, 385, 275, 65, 145, 434, 39

311, 202, 126, 494, 321, 330, 290, 28, 400, 84, 6, 160, 432, 308, 469, 459, 80, 48, 292, 229, 191, 240, 491, 231, 286, 413, 170, 486, 59, 54, 36, 334, 135, 39, 393, 201, 127, 95, 456, 497, 429, 139, 81, 293, 359, 477, 404, 129, 129, 297, 298, 495, 424, 446, 57, 296, 10, 269, 350, 337, 39, 386, 142, 327, 22, 352, 421, 32, 171, 452, 2, 484, 337, 359, 444, 246, 174, 23, 115, 102, 427, 439, 71, 478, 89, 225, 7, 118, 453, 350, 109, 277, 338, 474, 405, 380, 256, 228, 277, 3

Ich bin mir ziemlich sicher, dass es nicht einfach ist, eine optimale Lösung zu finden (da das regelmäßige Sortieren von Pfannkuchen der Fall ist).

2 Ja, Menschen mit sehr schnellen Computern können aufgrund des Zeitlimits von einer Minute Vorteile haben. Nach vielen Diskussionen habe ich herausgefunden, dass es am besten ist, wenn jeder sein eigenes Benchmarking durchführt. Es ist keine schnellste Code-Herausforderung.

Stewie Griffin
quelle
1
Etwas verwandt .
Stewie Griffin
1
Die optimale Lösung sollte höchstens der Einfügesortierung in der Anzahl der Umkehrungen entsprechen, jede Umkehrung kann eine einzelne Zahl platzieren.
Freitag,
3
Dies ist kein Pancake-Flipping (das nur von einer Stelle bis zum Ende flippen kann). Die Auswahlsortierung ist O (n) und verwendet n-1 Swaps. Es gibt schlimmste Fälle, in denen n-1-Swaps erforderlich sind. Auswahlsortierung ist asymptotisch optimal.
Orlp
1. Ist die Eingabe eine Liste / ein Vektor von ganzen Zahlen? 2. Was soll die Ausgabe des Programms sein? 3. Kann das Programm den Vektor oder Teile davon mehrmals sortieren, möglicherweise unter Verwendung verschiedener Methoden (wie z. B. Quicksort), um zu bestimmen, wie die Operationen optimiert werden sollen, sofern eine Subvektor-Umkehrsortierung der Eingabe durchgeführt wird Vektor (wie gewünscht) am Ende?
Aditsu
1
@orlp Kannst du beweisen, dass es schlimmste Fälle mit n-1Flips gibt? Ich kann nur eine Untergrenze von ca. 50 nachweisen.
user202729

Antworten:

6

Java, genetischer Algorithmus, 80 + 81 + 79 + 78 + 80 = 398 (vorher 418 )

Nachdem ich eine Reihe verschiedener Ideen ausprobiert hatte und die meisten fehlgeschlagen waren, entschied ich mich für diesen Algorithmus: Beginnen Sie mit dem Eingabearray, versuchen Sie alle möglichen Umkehrungen und behalten Sie eine bestimmte Anzahl von Ergebnissen mit der geringsten Anzahl von Durchläufen bei Wir erhalten ein sortiertes Array.

Mit "Durchläufen" meine ich maximale Unterfelder, die im sortierten Feld genau oder umgekehrt vorkommen. Grundsätzlich handelt es sich um maximal sortierte Subarrays. Bei wiederholten Elementen sollte die Anzahl der Elemente in der Mitte übereinstimmen. ZB wenn die sortierten Array wird 2, 2, 3, 3, 4, 4dann 4, 3, 3, 2ein Run , aber 2, 2, 3, 4nicht (und keiner ist 2, 3, 2).

In dieser Version habe ich den Algorithmus so optimiert, dass er nur an Laufgrenzen umkehrt und nur dann, wenn ein umgekehrter Lauf mit einem neu angrenzenden Lauf verbunden werden kann. Außerdem werden die Läufe bei jedem Schritt angepasst und verbunden, um zu vermeiden, dass sie aus dem geänderten Array neu berechnet werden. Dies ermöglichte es mir, die "Populationsgröße" von 30 auf etwa 3000 zu erhöhen und mehrere Simulationen mit verschiedenen Größen durchzuführen.

import java.io.*;
import java.util.*;

public class SubReversal {
    static int n;
    static int[] a;
    static int[] srt;
    static List<int[]> rev;
    static Map<Integer, Integer> idx;
    static Map<Integer, Integer> count;

    static final int NB = 2000;
    static State[] best = new State[NB + 1];
    static int ns;

    static class Run {
        int start;
        int end;
        int dir;
        int nstart = 1;
        int nend = 1;

        Run(final int start) {
            this.start = start;
        }

        Run(final Run r) {
            start = r.start;
            end = r.end;
            dir = r.dir;
            nstart = r.nstart;
            nend = r.nend;
        }

        Run copy() {
            return new Run(this);
        }

        Run reverse() {
            int t = start;
            start = end;
            end = t;
            t = nstart;
            nstart = nend;
            nend = t;
            dir = -dir;
            return this;
        }

        boolean canJoin(final Run r) {
            if (dir * r.dir == -1) {
                return false;
            }
            final int t = idx.get(a[r.start]) - idx.get(a[end]);
            if (Math.abs(t) > 1) {
                return false;
            }
            if (t != 0 && dir + r.dir != 0 && t != dir && t != r.dir) {
                return false;
            }
            if (t == 0) {
                if (dir * r.dir == 0) {
                    return true;
                }
                return nend + r.nstart == count.get(a[end]);
            }
            return (dir == 0 || nend == count.get(a[end])) && (r.dir == 0 || r.nstart == count.get(a[r.start]));
        }

        Run join(final Run r) {
            if (a[start] == a[r.start]) {
                nstart += r.nstart;
            }
            if (a[end] == a[r.end]) {
                nend += r.nend;
            }
            else {
                nend = r.nend;
            }
            end = r.end;
            if (dir == 0) {
                dir = r.dir;
            }
            if (dir == 0 && a[start] != a[end]) {
                dir = idx.get(a[end]) - idx.get(a[start]);
            }
            return this;
        }

        @Override
        public String toString() {
            return start + "(" + nstart + ") - " + end + '(' + nend + "): " + dir;
        }
    }

    static class State implements Comparable<State> {
        int[] b;
        int[] rv;
        State p;
        List<Run> runs;

        public State(final int[] b, final int[] rv, final State p, final List<Run> runs) {
            this.b = Arrays.copyOf(b, b.length);
            this.rv = rv;
            this.p = p;
            this.runs = runs;
        }

        @Override
        public int compareTo(final State o) {
            return runs.size() - o.runs.size();
        }

        @Override
        public String toString() {
            return Arrays.toString(b) + " - " + Arrays.toString(rv) + " - " + runs.size();
        }

        int getCount() {
            return p == null ? 0 : p.getCount() + 1;
        }
    }

    static void reverse(int x, int y) {
        while (x < y) {
            int t = a[x];
            a[x] = a[y];
            a[y] = t;
            x++;
            y--;
        }
    }

    static List<Run> runs() {
        final List<Run> l = new ArrayList<>();
        Run run = new Run(0);
        for (int i = 1; i < n; ++i) {
            final int t = idx.get(a[i]) - idx.get(a[i - 1]);
            if (Math.abs(t) > 1) {
                run.end = i - 1;
                l.add(run);
                run = new Run(i);
            }
            else if (t == 0) {
                run.nend++;
                if (run.dir == 0) {
                    run.nstart++;
                }
            }
            else {
                if (run.dir == 0) {
                    run.dir = t;
                }
                else if (run.dir != t || run.nend != count.get(a[i - 1])) {
                    run.end = i - 1;
                    l.add(run);
                    run = new Run(i);
                }
                run.nend = 1;
            }
        }
        run.end = n - 1;
        l.add(run);
        return l;
    }

    static void show() {
        if (!Arrays.equals(a, srt)) {
            System.out.println("bug!");
            System.out.println(Arrays.toString(a));
            throw new RuntimeException();
        }
        System.out.println("Sorted: " + Arrays.toString(a));
        System.out.println(rev.size() + " reversal(s):");
        for (int[] x : rev) {
            System.out.println(Arrays.toString(x));
        }
    }

    static void sort() {
        State bestest = null;
        final int[] a1 = Arrays.copyOf(a, n);
        final int[] sizes = {10, 20, 30, 50, 100, 200, 300, 500, 1000, 2000};

        for (int nb : sizes) {
            System.arraycopy(a1, 0, a, 0, n);
            ns = 1;
            best[0] = new State(a, null, null, runs());
            while (best[0].runs.size() > 1) {
                final State[] s = Arrays.copyOf(best, ns);
                ns = 0;
                for (State x : s) {
                    System.arraycopy(x.b, 0, a, 0, n);
                    final int m = x.runs.size();
                    for (int i = 0; i < m; ++i) {
                        for (int j = i; j < m; ++j) {
                            boolean b = false;
                            if (i > 0) {
                                final Run r = x.runs.get(j);
                                r.reverse();
                                b = x.runs.get(i - 1).canJoin(r);
                                r.reverse();
                            }
                            if (!b && j < m - 1) {
                                final Run r = x.runs.get(i);
                                r.reverse();
                                b = r.canJoin(x.runs.get(j + 1));
                                r.reverse();
                            }
                            if (!b) {
                                continue;
                            }
                            final List<Run> l = new ArrayList<>(x.runs);
                            final int rstart = l.get(i).start;
                            final int rend = l.get(j).end;
                            final int t = rstart + rend;
                            reverse(rstart, rend);
                            for (int k = i; k <= j; ++k) {
                                final Run r = x.runs.get(i + j - k).copy().reverse();
                                r.start = t - r.start;
                                r.end = t - r.end;
                                l.set(k, r);
                            }
                            if (j < m - 1 && l.get(j).canJoin(l.get(j + 1))) {
                                l.get(j).join(l.get(j + 1));
                                l.remove(j + 1);
                            }
                            if (i > 0 && l.get(i - 1).canJoin(l.get(i))) {
                                l.set(i - 1, l.get(i - 1).copy().join(l.get(i)));
                                l.remove(i);
                            }

                            if (ns < nb || l.size() < best[ns - 1].runs.size()) {
                                best[ns++] = new State(a, new int[]{rstart, rend}, x, l);
                                Arrays.sort(best, 0, ns);
                                if (ns > nb) {
                                    ns = nb;
                                }
                            }
                            reverse(rstart, rend);
                        }
                    }
                }

                if (ns == 0) {
                    for (State x : s) {
                        System.arraycopy(x.b, 0, a, 0, n);
                        final List<Run> l = new ArrayList<>(x.runs);
                        final int rstart = l.get(0).start;
                        final int rend = l.get(0).end;
                        final int t = rstart + rend;
                        reverse(rstart, rend);
                        final Run r = x.runs.get(0).copy().reverse();
                        r.start = t - r.start;
                        r.end = t - r.end;
                        l.set(0, r);

                        best[ns++] = new State(a, new int[]{rstart, rend}, x, l);
                        reverse(rstart, rend);
                    }
                    Arrays.sort(best, 0, ns);
                }
            }
            State r = null;
            for (int i = 0; i < ns; ++i) {
                if (Arrays.equals(best[i].b, srt)) {
                    r = best[i];
                    break;
                }
            }
            if (r == null) {
                final State x = best[0];
                System.arraycopy(x.b, 0, a, 0, n);
                reverse(0, n - 1);
                r = new State(a, new int[]{0, n - 1}, x, runs());
            }
            if (!Arrays.equals(r.b, srt)) {
                throw new RuntimeException("bug");
            }

            if (bestest == null || r.getCount() < bestest.getCount()) {
                bestest = r;
            }
        }

        while (bestest.p != null) {
            rev.add(bestest.rv);
            bestest = bestest.p;
        }
        Collections.reverse(rev);
        a = a1;
        for (int[] x : rev) {
            reverse(x[0], x[1]);
        }
        if (!Arrays.equals(a, srt)) {
            throw new RuntimeException("bug");
        }
    }

    static void init(final String s) {
        final String[] b = s.split(s.contains(",") ? "," : " ");
        n = b.length;
        a = new int[n];
        count = new HashMap<>();
        for (int i = 0; i < n; ++i) {
            a[i] = Integer.parseInt(b[i].trim());
            final Integer x = count.get(a[i]);
            count.put(a[i], x == null ? 1 : x + 1);
        }
        srt = Arrays.copyOf(a, n);
        Arrays.sort(srt);
        idx = new HashMap<>();
        int j = 0;
        for (int i = 0; i < n; ++i) {
            if (i == 0 || srt[i] != srt[i - 1]) {
                idx.put(srt[i], j++);
            }
        }
        rev = new ArrayList<>();
    }

    static void test5() {
        final String[] t = {"133, 319, 80, 70, 194, 333, 65, 21, 345, 142, 82, 491, 92, 167, 281, 386, 48, 101, 394, 130, 111, 139, 214, 337, 180, 24, 443, 35, 376, 13, 166, 59, 452, 429, 406, 256, 133, 435, 446, 304, 350, 364, 447, 471, 236, 177, 317, 342, 294, 146, 280, 32, 135, 399, 78, 251, 467, 305, 366, 309, 162, 473, 27, 67, 305, 497, 112, 399, 103, 178, 386, 343, 33, 134, 480, 147, 466, 244, 370, 140, 227, 292, 28, 357, 156, 367, 157, 60, 214, 280, 153, 445, 301, 108, 77, 404, 496, 3, 226, 37",
                "468, 494, 294, 42, 19, 23, 201, 47, 165, 118, 414, 371, 163, 430, 295, 333, 147, 336, 403, 490, 370, 128, 261, 91, 173, 339, 40, 54, 331, 236, 255, 33, 237, 272, 193, 91, 232, 452, 79, 435, 160, 328, 47, 179, 162, 239, 315, 73, 160, 266, 83, 451, 317, 255, 491, 70, 18, 275, 339, 298, 117, 145, 17, 178, 232, 59, 109, 271, 301, 437, 63, 103, 130, 15, 265, 281, 365, 444, 180, 257, 99, 248, 378, 158, 210, 466, 404, 263, 29, 117, 417, 357, 44, 495, 303, 428, 146, 215, 164, 99",
                "132, 167, 361, 145, 36, 56, 343, 330, 14, 412, 345, 263, 306, 462, 101, 453, 364, 389, 432, 32, 200, 76, 268, 291, 35, 13, 448, 188, 11, 235, 184, 439, 175, 159, 360, 46, 193, 440, 334, 128, 346, 192, 263, 466, 175, 407, 340, 393, 231, 472, 122, 254, 451, 485, 257, 67, 200, 135, 132, 421, 205, 398, 251, 286, 292, 488, 480, 56, 284, 484, 157, 264, 459, 6, 289, 311, 116, 138, 92, 21, 307, 172, 352, 199, 55, 38, 427, 214, 233, 404, 330, 105, 223, 495, 334, 169, 168, 444, 268, 248",
                "367, 334, 296, 59, 18, 193, 118, 10, 276, 180, 242, 115, 233, 40, 225, 244, 147, 439, 297, 115, 354, 248, 89, 423, 47, 458, 64, 33, 463, 142, 5, 13, 89, 282, 186, 12, 70, 289, 385, 289, 274, 136, 39, 424, 174, 186, 489, 73, 296, 39, 445, 308, 451, 384, 451, 446, 282, 419, 479, 220, 35, 419, 161, 14, 42, 321, 202, 30, 32, 162, 444, 215, 218, 102, 140, 473, 500, 480, 402, 1, 1, 79, 50, 54, 111, 189, 147, 352, 61, 460, 196, 77, 315, 304, 385, 275, 65, 145, 434, 39",
                "311, 202, 126, 494, 321, 330, 290, 28, 400, 84, 6, 160, 432, 308, 469, 459, 80, 48, 292, 229, 191, 240, 491, 231, 286, 413, 170, 486, 59, 54, 36, 334, 135, 39, 393, 201, 127, 95, 456, 497, 429, 139, 81, 293, 359, 477, 404, 129, 129, 297, 298, 495, 424, 446, 57, 296, 10, 269, 350, 337, 39, 386, 142, 327, 22, 352, 421, 32, 171, 452, 2, 484, 337, 359, 444, 246, 174, 23, 115, 102, 427, 439, 71, 478, 89, 225, 7, 118, 453, 350, 109, 277, 338, 474, 405, 380, 256, 228, 277, 3"};
        int r = 0;
        for (String s : t) {
            init(s);
            sort();
            System.out.println(rev.size());
            r += rev.size();
        }
        System.out.println("total: " + r);
    }

    public static void main(final String... args) throws IOException {
        System.out.print("Input: ");
        final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        final String s = br.readLine();
        final long t = System.currentTimeMillis();
        if (s.isEmpty()) {
            System.out.println("Running tests");
            test5();
        }
        else {
            init(s);
            sort();
            show();
        }
        System.out.println("Time: " + (System.currentTimeMillis() - t + 500) / 1000 + " sec");
    }
}

Die Eingabe ist eine Liste von Zahlen, die durch Komma und / oder Leerzeichen (von stdin) getrennt sind. Wenn die Eingabe leer ist, führt das Programm die 5 Tests durch. Jeder dauert hier ungefähr 40 Sekunden.

aditsu
quelle
Interessant, dass sich die Anzahl der Umkehrungen im 5. Testfall mit der neuen Version nicht verbessert hat. Die anderen verbessern sich sehr. Ich bin froh, dass Sie beschlossen haben, es noch einmal zu versuchen :)
Stewie Griffin
@StewieGriffin danke, du hast mir geholfen, über 20k zu blasen :) Ich glaube, ich hatte ein bisschen Glück mit dem letzten Fall zuvor. Ein randomisierter Ansatz wird wahrscheinlich noch bessere Ergebnisse liefern.
Aditsu
5

Ein Zug Brute-Force, dann Auswahlsortierung (auch naive Lösung), 90 + 89 + 88 + 87 + 89 = 443 Züge

let doReverse = (a, l, r) => {
  a.splice(l, r - l, ...a.slice(l, r).reverse());
};
let selectSubVectorReverseSort = a => {
  let log = [];

  for (let i = 0, l = a.length; i < l; i++) {
    let j, p = i;
    for (j = i; j < l; j++) {
      if (a[j] < a[p]) p = j;
    }
    if (p === i) continue;
    log.push([i, p + 1]);
    doReverse(a, i, p + 1);
  }
  return log;
};

let a = JSON.parse(`[${readline()}]`);
let copiedArray = a => a.map(x => x);
let minLog = selectSubVectorReverseSort(copiedArray(a));
for (let i = 0, l = a.length; i < l; i++) {
  for (let j = i + 1; j < l; j++) {
    let b = copiedArray(a);
    doReverse(b, i, j + 1);
    let log = [[i, j + 1], ...selectSubVectorReverseSort(b)];
    if (log.length < minLog.length) minLog = log;
  }
}

print(minLog.length);

Versuchen Sie es für jeden möglichen ersten Schritt und führen Sie dann eine Auswahlsortierung durch.

Ja, das ist eine andere naive Lösung.

Ich bin mir nicht sicher, ob dies eine Bearbeitung oder ein anderer Beitrag sein soll, aber es scheint, dass die Lösung zu einfach ist, sodass die Bearbeitung ausgewählt wird.


Auswahl sortieren (Naive Lösung), 92 + 93 + 95 + 93 + 96 = 469 Züge

let log = [];
let doReverse = (a, l, r) => {
  log.push([l, r]);
  a.splice(l, r - l, ...a.slice(l, r).reverse());
}

let a = JSON.parse(`[${readline()}]`);
for (let i = 0, l = a.length; i < l; i++) {
  let j, p = i;
  for (j = i; j < l; j++) {
    if (a[j] < a[p]) p = j;
  }
  if (p === i) continue;
  doReverse(a, i, p + 1);
}
print(log.length)

Eine naive Lösung verwenden Auswahlsortierung.

Es MUSS einige bessere Lösungen geben, aber poste dies, da ich keine bessere gefunden habe (ohne Brute-Force-Suche).

(Der obige Code ist JavaScript Shell )

tsh
quelle