Rotate Array
Hai un array di numeri interi nums e un numero k. Ruota l'array verso destra di k passi: a ogni passo, ogni valore si sposta di una posizione verso destra e l'ultimo valore torna in testa. Restituisci l'array ruotato.
k può essere molto più grande della lunghezza dell'array.
Funzione
- numsinteger-array
- l'array di interi da ruotare
- kinteger
- quanti passi ruotare verso destra
- Restituisceinteger-array
- nums ruotato a destra di k posizioni
Vincoli
1 ≤ nums.length ≤ 5000-104 ≤ nums[i] ≤ 1040 ≤ k ≤ 109
Esempi
- Input
- nums = [4, 9, 1, 6, 3]k = 2
- Output
- [6, 3, 4, 9, 1]
- Spiegazione
- Due passi verso destra portano in testa gli ultimi due valori, 6 e 3. Gli altri tre valori si spostano di due posizioni a destra e mantengono il loro ordine:
[6, 3, 4, 9, 1].
- Input
- nums = [10, 20, 30]k = 7
- Output
- [30, 10, 20]
- Spiegazione
- Ogni 3 passaggi riportano un array di lunghezza 3 al punto di partenza, quindi 7 passaggi equivalgono a 7 mod 3 = 1 passaggio. Un passaggio sposta 30 in prima posizione.
- Input
- nums = [-5, 8]k = 4
- Output
- [-5, 8]
- Spiegazione
- 4 mod 2 = 0, quindi dopo 4 passaggi ogni valore è di nuovo al suo posto e l'array torna invariato.
Per approfondire
Puoi ruotare sul posto spostando ogni valore direttamente in (i + k) mod n e continuando con il valore che sposta? Quanti cicli si formano?
Suggerimenti
Aprili uno alla volta. Ognuno rivela un po’ di più.
Un array di lunghezza
nritorna all'ordine iniziale doponpassaggi. Quanti passaggi contano davvero quandokè 10^9?Dopo la rotazione, gli ultimi
k mod nvalori formano la parte iniziale dell’array e il resto li segue, mantenendo ciascun blocco il proprio ordine precedente. Dove finisce il valore all’indicei?Invertire l’intero array mette il blocco finale all’inizio, ma entrambi i blocchi risultano al contrario. Inverti ogni blocco un’altra volta per ripristinarne l’ordine. Ogni inversione consiste in due indici che avanzano l’uno verso l’altro.
Soluzione
Ogni n passi riportano l’array al punto di partenza, quindi prima riduci k, che può essere 10^9, a k mod n. Poi scrivi ogni valore direttamente al suo indice finale in un secondo array, oppure ottieni lo stesso risultato all’interno dell’array con tre inversioni e O(1) memoria aggiuntiva.
Copia ogni valore nel suo nuovo indice
Intuizione
Dopo k passaggi, il valore all’indice i si trova in (i + k) mod n, quindi scrivilo direttamente lì senza eseguire i passaggi. Riduci prima k a k mod n: una rotazione di n riporta ogni valore nella posizione iniziale, quindi con k = 7 e n = 3 resta un solo passaggio.
Un’unica iterazione posiziona tutti gli n valori: tempo O(n), più memoria O(n) per il risultato. Non puoi scrivere direttamente in nums in questo modo, perché ogni scrittura sovrascriverebbe un valore che non hai ancora spostato.
Algoritmo
- Imposta
nalla lunghezza dinumse sostituiscikconk mod n. - Crea un array risultato di lunghezza
n. - Per ogni indice
i, memorizzanums[i]inresult[(i + k) mod n]. - Restituisci il risultato.
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 resultTre inversioni sul posto
Intuizione
Dividi l'array in A, i primi n-k valori, e B, gli ultimi k. L'array ruotato è B seguito da A, ciascun blocco nel suo ordine originale. Invertire l'intero array capovolge sia l'ordine dei blocchi sia l'ordine all'interno di ciascuno, quindi B viene prima ma è al contrario, e lo stesso vale per A. Invertendo di nuovo ciascun blocco se ne ripristina l'ordine interno.
Per [4, 9, 1, 6, 3] e k = 2: invertendo tutto si ottiene [3, 6, 1, 9, 4], invertendo i primi due si ottiene [6, 3, 1, 9, 4] e invertendo gli ultimi tre si ottiene [6, 3, 4, 9, 1].
Ogni valore viene scambiato al massimo due volte, quindi il tempo è O(n) e la memoria aggiuntiva è costituita da alcune variabili indice (O(n) in R, che copia il vettore quando la funzione helper di inversione lo modifica).
Algoritmo
- Imposta
nalla lunghezza dinumse sostituiscikconk mod n. - Inverti l'intero array, dagli indici 0 a
n-1. - Inverti il primo blocco, dagli indici 0 a
k-1. - Inverti il secondo blocco, dagli indici
kan-1. - Restituisci
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
Trappole e casi limite
- Dimenticare
k mod n. Conk = 10^9, ruotare passo dopo passo non finisce mai, e invertire i primikvalori legge ben oltre la fine dell'array. - Suddividere senza usare il modulo. In Python,
nums[-k:] + nums[:-k]conk = 7en = 3restituisce l'array invariato, perché entrambe le sezioni si fermano al limite dell'array. - Invertire nell'ordine sbagliato. Invertire prima i due blocchi e per ultimo l'intero array produce una rotazione a sinistra.
- Errore di un'unità al limite del blocco: il primo blocco termina all'indice
k-1e il secondo inizia dak. In Lua e R, che contano a partire da 1, i blocchi sono1..kek+1..n.
Domande frequenti3
Qual è la complessità temporale di Rotate Array?
O(n) sia per l’approccio con copia sia per le tre inversioni, perché ogni valore viene spostato un numero costante di volte. Ridurre prima k con k mod n impedisce che un k enorme abbia importanza. Ruotare di un passo alla volta costa invece O(n × k).
Che cosa succede quando k è maggiore della lunghezza dell’array?
Ogni n passaggi riportano l’array all’ordine iniziale, quindi contano solo k mod n passaggi. Ruotare [10, 20, 30] di 7 è come ruotarlo di 1, ottenendo [30, 10, 20]. Quando k è un multiplo di n, l’array non cambia.
Come si ruota un array verso sinistra?
Una rotazione a sinistra di k è una rotazione a destra di n - (k mod n). Con le inversioni, inverti i primi k mod n valori, poi il resto e infine l'intero array. Entrambi i metodi richiedono un tempo O(n).
Problemi simili
Problemi che usano le stesse idee. Risolverne due o tre è ciò che fissa uno schema.
def rotate(nums, k):
# Scrivi il codice quiTest #1
Test #2
Test #3
Argomenti
nums = [4, 9, 1, 6, 3] k = 2
Output atteso
[6, 3, 4, 9, 1]