0Pricing
Coding Interview Prep · Lektion

Binäre Suche in rotierten und unsortierten Arrays

Lösen Sie search-in-rotated-sorted-array und find-minimum-in-rotated-array, indem Sie in jedem Schritt entscheiden, welche Hälfte sortiert ist.

Binäre Suche in rotierten und unsortierten Arrays ist eine kostenlose Coding Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Coding Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Was ist ein rotiertes sortiertes Array?

Ein rotiertes sortiertes Array ist ein sortiertes Array, das an einem bestimmten Drehpunkt geteilt wurde und dessen beide Teile vertauscht wurden. Beispielsweise ist [4, 5, 6, 7, 0, 1, 2] das bei Index 4 rotierte sortierte Array [0,1,2,4,5,6,7]. Die standardmäßige binäre Suche schlägt hier fehl, weil das Array nicht mehr global sortiert ist.

Die zentrale Erkenntnis ist, dass nach jeder Rotation mindestens eine Hälfte des Arrays immer sortiert ist. Ihre binäre Suche muss erkennen, welche Hälfte sortiert ist, bevor sie entscheidet, wie die Grenzen verschoben werden.

# A rotated sorted array — one half is always sorted
arr = [4, 5, 6, 7, 0, 1, 2]
# Left half [4,5,6,7] is sorted
# Right half [0,1,2] is also sorted
# But left[0]=4 > right[-1]=2 => rotation happened in left-to-right crossing

Die sortierte Hälfte erkennen

Nachdem Sie mid berechnet haben, vergleichen Sie arr[lo] mit arr[mid]. Wenn arr[lo] <= arr[mid] gilt, ist die linke Hälfte sortiert; andernfalls ist die rechte Hälfte sortiert. Sobald Sie wissen, welche Hälfte sortiert ist, können Sie prüfen, ob das Ziel in diesem sortierten Bereich liegt, und die Suche entsprechend eingrenzen.

Mit diesem Entscheidungsbaum können Sie in jedem Schritt genau die Hälfte des Arrays verwerfen. Dadurch bleibt die Komplexität auch bei einem rotierten Array O(log n).

def search_rotated(nums, target):
    lo, hi = 0, len(nums) - 1
    while lo <= hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] == target:
            return mid
        # Left half is sorted
        if nums[lo] <= nums[mid]:
            if nums[lo] <= target < nums[mid]:
                hi = mid - 1
            else:
                lo = mid + 1
        # Right half is sorted
        else:
            if nums[mid] < target <= nums[hi]:
                lo = mid + 1
            else:
                hi = mid - 1
    return -1

print(search_rotated([4, 5, 6, 7, 0, 1, 2], 0))  # 4
print(search_rotated([4, 5, 6, 7, 0, 1, 2], 3))  # -1

Ein Beispiel Schritt für Schritt nachvollziehen

Verfolgen wir search_rotated([4,5,6,7,0,1,2], 0) Schritt für Schritt. Zu Beginn gilt lo=0, hi=6, mid=3, arr[mid]=7. Liegt das Ziel 0 in der sortierten linken Hälfte [4..7]? Nein, also setzen wir lo=4. Nun gilt lo=4, hi=6, mid=5, arr[mid]=1. Die linke Hälfte [0,1] ist sortiert (arr[lo]=0 <= arr[mid]=1). Liegt 0 in [0..1)? Ja, also setzen wir hi=4. Nun gilt lo=4, hi=4, mid=4, arr[4]=0 — das Element wurde an Index 4 gefunden.

# Step-by-step trace
nums = [4, 5, 6, 7, 0, 1, 2]
target = 0
steps = []
lo, hi = 0, len(nums) - 1
while lo <= hi:
    mid = lo + (hi - lo) // 2
    steps.append(f'lo={lo} hi={hi} mid={mid} val={nums[mid]}')
    if nums[mid] == target:
        steps.append(f'Found at {mid}')
        break
    if nums[lo] <= nums[mid]:
        if nums[lo] <= target < nums[mid]:
            hi = mid - 1
        else:
            lo = mid + 1
    else:
        if nums[mid] < target <= nums[hi]:
            lo = mid + 1
        else:
            hi = mid - 1
for s in steps:
    print(s)

Duplikate bei der Rotation behandeln

Wenn das rotierte Array Duplikate enthalten kann (z. B. [1,3,1,1,1]), ist die Bedingung nums[lo] == nums[mid] nicht eindeutig — Sie können nicht feststellen, welche Hälfte sortiert ist. Die sichere Lösung besteht darin, lo um eins zu erhöhen (oder hi um eins zu verringern) und es erneut zu versuchen. Dadurch verschlechtert sich die Laufzeit im Worst Case auf O(n). Diesen Umstand sollten Sie im Vorstellungsgespräch erwähnen.

def search_rotated_with_dups(nums, target):
    lo, hi = 0, len(nums) - 1
    while lo <= hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] == target:
            return True
        # Ambiguous: shrink left boundary
        if nums[lo] == nums[mid] == nums[hi]:
            lo += 1
            hi -= 1
        elif nums[lo] <= nums[mid]:
            if nums[lo] <= target < nums[mid]:
                hi = mid - 1
            else:
                lo = mid + 1
        else:
            if nums[mid] < target <= nums[hi]:
                lo = mid + 1
            else:
                hi = mid - 1
    return False

print(search_rotated_with_dups([1, 3, 1, 1, 1], 3))  # True
print(search_rotated_with_dups([2, 2, 2, 0, 2], 0))  # True

Das Minimum in einem rotierten sortierten Array finden

Bei einer verwandten Aufgabe soll das Minimum in einem rotierten sortierten Array gefunden werden, ohne nach einem bestimmten Zielwert zu suchen. Das Minimum liegt immer in der unsortierten Hälfte. In jedem Schritt gilt: Wenn arr[mid] > arr[hi], liegt das Minimum in der rechten Hälfte (lo = mid + 1); andernfalls liegt es in der linken Hälfte einschließlich mid (hi = mid). Sobald lo == hi gilt, haben Sie das Minimum gefunden.

def find_min(nums):
    lo, hi = 0, len(nums) - 1
    while lo < hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] > nums[hi]:
            lo = mid + 1   # min is in right half
        else:
            hi = mid       # min is at mid or left of mid
    return nums[lo]

print(find_min([3, 4, 5, 1, 2]))   # 1
print(find_min([4, 5, 6, 7, 0, 1, 2]))  # 0
print(find_min([11, 13, 15, 17]))  # 11 (no rotation)

Warum arr[lo] <= arr[mid] die linke Hälfte als sortiert erkennt

Die Bedingung arr[lo] <= arr[mid] funktioniert, weil in einem sortierten (oder nicht rotierten) Abschnitt das erste Element immer das kleinste ist. Wenn arr[lo] <= arr[mid] gilt, wurde innerhalb von [lo..mid] keine Rotation durchgeführt, sodass diese Hälfte sortiert ist. Die Gleichheit berücksichtigt den Fall lo == mid (ein Abschnitt mit einem einzigen Element ist trivialerweise sortiert).

Wenn dagegen arr[lo] > arr[mid] gilt, muss der Rotations-Pivot zwischen lo und mid liegen. Daher ist die rechte Hälfte [mid..hi] der zusammenhängende sortierte Abschnitt.

# Visualise: detect which half is sorted
examples = [
    ([4, 5, 6, 7, 0, 1, 2], 0, 6),  # mid=3, val=7 => left sorted
    ([6, 7, 0, 1, 2, 4, 5], 0, 6),  # mid=3, val=1 => right sorted
]
for arr, lo, hi in examples:
    mid = lo + (hi - lo) // 2
    if arr[lo] <= arr[mid]:
        print(f'arr[{lo}]={arr[lo]} <= arr[{mid}]={arr[mid]}  => LEFT half sorted')
    else:
        print(f'arr[{lo}]={arr[lo]} >  arr[{mid}]={arr[mid]}  => RIGHT half sorted')

Komplexitätsanalyse

Die Suche in einem rotierten sortierten Array mit binärer Suche benötigt weiterhin O(log n) Zeit und O(1) Speicherplatz, da wir den Suchbereich in jeder Iteration halbieren. Der einzige Unterschied zur klassischen binären Suche ist eine zusätzliche Prüfung mit konstanter Laufzeit, um festzustellen, welche Hälfte sortiert ist.

Bei Duplikaten verschlechtert sich die Laufzeit im Worst Case auf O(n), weil wir lo in jedem Schritt möglicherweise nur um eins erhöhen können. Erwähnen Sie diesen Kompromiss ausdrücklich — dadurch zeigen Sie, dass Sie auch über Randfälle jenseits des normalen Ablaufs nachdenken.

LeetCode 33 Schritt für Schritt

LeetCode 33 „Search in Rotated Sorted Array“ ist die kanonische Form dieser Aufgabe. Die Einschränkungen garantieren keine Duplikate und genau eine Rotation. Die Lösung ist die zuvor geschriebene Funktion search_rotated. Wichtige Punkte im Vorstellungsgespräch: Nennen Sie immer die Annahme, dass keine Duplikate vorhanden sind, überprüfen Sie Ihre Ungleichungen anhand eines konkreten Beispiels an der Grenze und stellen Sie sicher, dass der zurückgegebene Index sowohl im Fall eines gefundenen als auch im Fall eines nicht gefundenen Elements korrekt ist.

# LeetCode 33 — complete solution
def search(nums, target):
    lo, hi = 0, len(nums) - 1
    while lo <= hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] == target:
            return mid
        if nums[lo] <= nums[mid]:        # left half sorted
            if nums[lo] <= target < nums[mid]:
                hi = mid - 1
            else:
                lo = mid + 1
        else:                            # right half sorted
            if nums[mid] < target <= nums[hi]:
                lo = mid + 1
            else:
                hi = mid - 1
    return -1

# Tests
print(search([4,5,6,7,0,1,2], 0))   # 4
print(search([4,5,6,7,0,1,2], 3))   # -1
print(search([1], 0))               # -1

LeetCode 153: Minimum ohne Duplikate finden

LeetCode 153 „Find Minimum in Rotated Sorted Array“ verlangt, das Minimum ohne Duplikate zu finden. Vergleichen Sie dazu arr[mid] mit arr[hi] (nicht mit arr[lo]), um zu bestimmen, auf welcher Seite das Minimum liegt. Wenn arr[mid] > arr[hi] gilt, liegt das Minimum rechts; andernfalls liegt es bei mid oder links davon. So nähern Sie sich dem Minimum in O(log n).

def findMin(nums):
    lo, hi = 0, len(nums) - 1
    while lo < hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] > nums[hi]:
            lo = mid + 1
        else:
            hi = mid
    return nums[lo]

print(findMin([3,4,5,1,2]))         # 1
print(findMin([4,5,6,7,0,1,2]))     # 0
print(findMin([11,13,15,17]))       # 11

Rotationsanzahl und Pivot-Index

Sobald Sie das Minimum finden können, kennen Sie auch die Rotationsanzahl: Der Index des Minimums entspricht genau der Anzahl der Positionen, um die das Array nach rechts rotiert wurde. Im Beispiel [4,5,6,7,0,1,2] liegt das Minimum an Index 4, also wurde das Array um 4 Positionen rotiert.

Wenn Sie den Pivot kennen, können Sie eine Standard-Binärsuche anwenden, indem Sie die Indizes modulo n behandeln: real_idx = (mid + pivot) % n. Diese alternative Formulierung kann die Überlegungen bei der Arbeit mit zirkulär indizierten Strukturen vereinfachen.

def search_via_pivot(nums, target):
    n = len(nums)
    # Find pivot (index of minimum)
    lo, hi = 0, n - 1
    while lo < hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] > nums[hi]:
            lo = mid + 1
        else:
            hi = mid
    pivot = lo
    # Binary search with offset
    lo, hi = 0, n - 1
    while lo <= hi:
        mid = lo + (hi - lo) // 2
        real_mid = (mid + pivot) % n
        if nums[real_mid] == target:
            return real_mid
        elif nums[real_mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

print(search_via_pivot([4,5,6,7,0,1,2], 0))  # 4

Alles zusammenführen

Wenn Sie in einem Vorstellungsgespräch auf eine Aufgabe mit einem rotierten Array stoßen, folgen Sie diesem Entscheidungsbaum. Bestimmen Sie zunächst, ob Sie ein Ziel finden oder das Minimum finden müssen. Verwenden Sie zum Finden eines Zielwerts den Ansatz zur Erkennung der sortierten Hälfte. Um das Minimum zu finden, vergleichen Sie mid mit hi. Wenn Duplikate möglich sind, erwähnen Sie den Worst Case O(n) und ergänzen Sie die Fallback-Logik zum Verkleinern des Randbereichs.

Üben Sie, indem Sie Ihren Code anhand der drei klassischen Beispiele nachvollziehen: keine Rotation, einmal rotiert und so rotiert, dass das Minimum an der letzten Position steht.

Kurzer Test

Testen Sie Ihr Verständnis der Konzepte aus dieser Lektion zu Data Structures & Algorithms — Coding Interview Prep.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Ein rotiertes sortiertes Array hat immer mindestens eine sortierte Hälfte, Vergleichen Sie arr[lo] mit arr[mid], um vor der Entscheidung über den weiteren Suchbereich die sortierte Hälfte zu bestimmen, und zum Finden des Minimums wird arr[mid] mit arr[hi] verglichen, um den Rotations-Pivot zu lokalisieren. Als Nächstes sehen wir uns Varianten der binären Suche mit Lower Bound und Upper Bound an.

Häufig gestellte Fragen

Ist die Lektion „Binäre Suche in rotierten und unsortierten Arrays“ kostenlos?

Ja — der vollständige Text von „Binäre Suche in rotierten und unsortierten Arrays“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Coding Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Binäre Suche in rotierten und unsortierten Arrays“?

Lösen Sie search-in-rotated-sorted-array und find-minimum-in-rotated-array, indem Sie in jedem Schritt entscheiden, welche Hälfte sortiert ist. Du übst Coding Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Coding Interview Prep zu starten?

Keine Vorkenntnisse erforderlich. Coding Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Binäre Suche in rotierten und unsortierten Arrays“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Coding Interview Prep-Lektion Code schreiben und ausführen?

Ja. Jede Coding Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Klassische binäre Suche: links, rechts, Mitte
  2. Binäre Suche in rotierten und unsortierten Arrays
  3. Untere und obere Grenze
  4. Binäre Suche im Lösungsraum
← Zurück zu Coding Interview Prep