Rotate Array
Otrzymujesz tablicę liczb całkowitych nums oraz liczbę k. Obróć tablicę w prawo o k kroków: w jednym kroku każda wartość przesuwa się o jedno miejsce w prawo, a ostatnia wartość zawija się na początek. Zwróć obróconą tablicę.
k może być znacznie większe niż długość tablicy.
Funkcja
- numsinteger-array
- tablica liczb całkowitych do obrócenia
- kinteger
- o ile kroków obrócić w prawo
- Zwracainteger-array
- tablica nums przesunięta w prawo o k pozycji
Ograniczenia
1 ≤ nums.length ≤ 5000-104 ≤ nums[i] ≤ 1040 ≤ k ≤ 109
Przykłady
- Wejście
- nums = [4, 9, 1, 6, 3]k = 2
- Wyjście
- [6, 3, 4, 9, 1]
- Wyjaśnienie
- Dwa kroki w prawo przenoszą dwie ostatnie wartości, 6 i 3, na początek. Pozostałe trzy wartości przesuwają się o dwa miejsca w prawo i zachowują swoją kolejność:
[6, 3, 4, 9, 1].
- Wejście
- nums = [10, 20, 30]k = 7
- Wyjście
- [30, 10, 20]
- Wyjaśnienie
- Co 3 kroki tablica o długości 3 wraca do miejsca, w którym się zaczęła, więc 7 kroków działa jak 7 mod 3 = 1 krok. Jeden krok przesuwa 30 na początek.
- Wejście
- nums = [-5, 8]k = 4
- Wyjście
- [-5, 8]
- Wyjaśnienie
- 4 mod 2 = 0, więc po 4 krokach każda wartość wraca na swoje miejsce, a tablica pozostaje bez zmian.
Pytanie dodatkowe
Czy możesz obracać tablicę w miejscu, przenosząc każdą wartość bezpośrednio do (i + k) mod n i przenosząc dalej wartość, którą zastąpi? Ile cykli to tworzy?
Podpowiedzi
Otwieraj je po kolei. Każda zdradza trochę więcej.
Tablica o długości
nwraca do początkowego porządku ponkrokach. Ile kroków ma faktyczne znaczenie, gdykwynosi 10^9?Po obrocie ostatnie wartości
k mod ntworzą początek tablicy, a za nimi następuje reszta — każdy blok zachowuje swoją wcześniejszą kolejność. Gdzie znajdzie się wartość o indeksiei?Odwrócenie całej tablicy umieszcza ostatni blok na początku, ale oba bloki są odwrócone. Odwróć każdy blok jeszcze raz, aby przywrócić ich kolejność. Każde odwrócenie polega na przesuwaniu się dwóch indeksów ku sobie.
Rozwiązanie
Co każde n kroków tablica wraca do stanu początkowego, więc najpierw zredukuj k, które może wynosić 10^9, do k mod n. Następnie zapisz każdą wartość bezpośrednio pod jej końcowym indeksem w drugiej tablicy albo uzyskaj ten sam rezultat w tej tablicy za pomocą trzech odwróceń i dodatkowej pamięci O(1).
Skopiuj każdą wartość na jej nowy indeks
Intuicja
Po k krokach wartość na indeksie i znajduje się pod indeksem (i + k) mod n, więc zapisz ją bezpośrednio w tym miejscu, bez wykonywania tych kroków. Najpierw zredukuj k do k mod n: obrót o n przywraca każdą wartość na jej poprzednie miejsce, więc gdy k = 7 i n = 3, pozostaje tylko jeden krok.
Jedno przejście umieszcza wszystkie n wartości: czas O(n) oraz pamięć O(n) na wynik. W ten sposób nie możesz zapisywać bezpośrednio do nums, ponieważ każdy zapis nadpisałby wartość, której jeszcze nie przeniesiono.
Algorytm
- Ustaw
nna długośćnumsi zastąpkprzezk mod n. - Utwórz tablicę wynikową o długości
n. - Dla każdego indeksu
izapisznums[i]pod indeksemresult[(i + k) mod n]. - Zwróć wynik.
def rotate(nums, k):
n = len(nums)
k %= n # a full turn of n steps changes nothing
result = [0] * n
for i in range(n):
result[(i + k) % n] = nums[i]
return resultTrzy odwrócenia na miejscu
Intuicja
Podziel tablicę na A, pierwsze n-k wartości, oraz B, ostatnie k wartości. Obrócona tablica to B, po której następuje A, przy czym każdy blok zachowuje swoją pierwotną kolejność. Odwrócenie całej tablicy zmienia kolejność bloków i kolejność elementów wewnątrz każdego z nich, więc B jest pierwsze, ale ma odwróconą kolejność, podobnie jak A. Ponowne odwrócenie każdego bloku przywraca pierwotną kolejność jego elementów.
Dla [4, 9, 1, 6, 3] i k = 2: odwrócenie wszystkiego daje [3, 6, 1, 9, 4], odwrócenie pierwszych dwóch elementów daje [6, 3, 1, 9, 4], a odwrócenie ostatnich trzech daje [6, 3, 4, 9, 1].
Każda wartość jest zamieniana miejscami najwyżej dwa razy, więc czas działania wynosi O(n), a dodatkowa pamięć obejmuje kilka zmiennych indeksowych (O(n) w R, które kopiuje wektor, gdy funkcja pomocnicza odwracająca go zmienia).
Algorytm
- Ustaw
nna długośćnumsi zastąpkprzezk mod n. - Odwróć całą tablicę, indeksy od 0 do
n-1. - Odwróć pierwszy blok, indeksy od 0 do
k-1. - Odwróć drugi blok, indeksy od
kdon-1. - Zwróć
nums.
def rotate(nums, k):
n = len(nums)
k %= n # a full turn of n steps changes nothing
def reverse(left, right):
while left < right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
reverse(0, n - 1) # the last k values come to the front, backwards
reverse(0, k - 1) # put the front block back in order
reverse(k, n - 1) # and the back block
return nums
Pułapki i przypadki brzegowe
- Pomijanie
k mod n. Przyk = 10^9obracanie krok po kroku nigdy się nie kończy, a odwrócenie pierwszychkwartości powoduje odczyt daleko poza końcem tablicy. - Wycinkowanie bez modulo. W Pythonie
nums[-k:] + nums[:-k]przyk = 7in = 3zwraca niezmienioną tablicę, ponieważ oba wycinki kończą się na krawędzi tablicy. - Odwracanie w niewłaściwej kolejności. Odwrócenie najpierw dwóch bloków, a na końcu całej tablicy, daje rotację w lewo.
- Błąd o jeden na granicy bloku: pierwszy blok kończy się na indeksie
k-1, a drugi zaczyna się odk. W Lua i R, w których indeksowanie zaczyna się od 1, bloki to1..kik+1..n.
Najczęstsze pytania3
Jaka jest złożoność czasowa algorytmu Rotate Array?
O(n) zarówno dla podejścia z kopiowaniem, jak i trzech odwróceń, ponieważ każda wartość jest przenoszona stałą liczbę razy. Najpierw zredukowanie k za pomocą k mod n sprawia, że duża wartość k nie ma znaczenia. Obracanie o jeden krok naraz kosztuje za to O(n × k).
Co się stanie, gdy k będzie większe niż długość tablicy?
Co n kroków tablica wraca do początkowego układu, więc znaczenie ma tylko k mod n kroków. Obrócenie [10, 20, 30] o 7 kroków daje ten sam efekt co obrócenie jej o 1 krok, co daje [30, 10, 20]. Gdy k jest wielokrotnością n, tablica się nie zmienia.
Jak obrócić tablicę w lewo?
Obrót w lewo o k to obrót w prawo o n - (k mod n). Przy użyciu odwracania odwróć pierwsze k mod n wartości, następnie pozostałe, a na końcu całą tablicę. W obu przypadkach czas działania wynosi O(n).
Podobne zadania
Zadania oparte na tych samych pomysłach. Rozwiązanie dwóch lub trzech utrwala schemat.
def rotate(nums, k):
# Wpisz kod tutajTest #1
Test #2
Test #3
Argumenty
nums = [4, 9, 1, 6, 3] k = 2
Oczekiwany wynik
[6, 3, 4, 9, 1]