数组
数学
双指针
题目描述
给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入: nums = [-1,-100,3,99], k = 2
输出: [3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
进阶:
尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1)
的 原地 算法解决这个问题吗?
解法
方法一:三次翻转
我们不妨记数组长度为 $n$,然后将 $k$ 对 $n$ 取模,得到实际需要旋转的步数 $k$。
接下来,我们进行三次翻转,即可得到最终结果:
将整个数组翻转
将前 $k$ 个元素翻转
将后 $n - k$ 个元素翻转
举个例子,对于数组 $[1, 2, 3, 4, 5, 6, 7]$, $k = 3$, $n = 7$, $k \bmod n = 3$。
第一次翻转,将整个数组翻转,得到 $[7, 6, 5, 4, 3, 2, 1]$。
第二次翻转,将前 $k$ 个元素翻转,得到 $[5, 6, 7, 4, 3, 2, 1]$。
第三次翻转,将后 $n - k$ 个元素翻转,得到 $[5, 6, 7, 1, 2, 3, 4]$,即为最终结果。
时间复杂度 $O(n)$,其中 $n$ 为数组长度。空间复杂度 $O(1)$。
Python3 Java C++ Go TypeScript Rust JavaScript C#
1
2
3
4
5
6
7
8
9
10
11
12 class Solution :
def rotate ( self , nums : List [ int ], k : int ) -> None :
def reverse ( i : int , j : int ):
while i < j :
nums [ i ], nums [ j ] = nums [ j ], nums [ i ]
i , j = i + 1 , j - 1
n = len ( nums )
k %= n
reverse ( 0 , n - 1 )
reverse ( 0 , k - 1 )
reverse ( k , n - 1 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 class Solution {
private int [] nums ;
public void rotate ( int [] nums , int k ) {
this . nums = nums ;
int n = nums . length ;
k %= n ;
reverse ( 0 , n - 1 );
reverse ( 0 , k - 1 );
reverse ( k , n - 1 );
}
private void reverse ( int i , int j ) {
for (; i < j ; ++ i , -- j ) {
int t = nums [ i ] ;
nums [ i ] = nums [ j ] ;
nums [ j ] = t ;
}
}
}
class Solution {
public :
void rotate ( vector < int >& nums , int k ) {
int n = nums . size ();
k %= n ;
reverse ( nums . begin (), nums . end ());
reverse ( nums . begin (), nums . begin () + k );
reverse ( nums . begin () + k , nums . end ());
}
};
1
2
3
4
5
6
7
8
9
10
11
12 func rotate ( nums [] int , k int ) {
n := len ( nums )
k %= n
reverse := func ( i , j int ) {
for ; i < j ; i , j = i + 1 , j - 1 {
nums [ i ], nums [ j ] = nums [ j ], nums [ i ]
}
}
reverse ( 0 , n - 1 )
reverse ( 0 , k - 1 )
reverse ( k , n - 1 )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 /**
Do not return anything, modify nums in-place instead.
*/
function rotate ( nums : number [], k : number ) : void {
const n : number = nums . length ;
k %= n ;
const reverse = ( i : number , j : number ) : void => {
for (; i < j ; ++ i , -- j ) {
const t : number = nums [ i ];
nums [ i ] = nums [ j ];
nums [ j ] = t ;
}
};
reverse ( 0 , n - 1 );
reverse ( 0 , k - 1 );
reverse ( k , n - 1 );
}
impl Solution {
pub fn rotate ( nums : & mut Vec < i32 > , k : i32 ) {
let n = nums . len ();
let k = ( k as usize ) % n ;
nums . reverse ();
nums [ .. k ]. reverse ();
nums [ k .. ]. reverse ();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 /**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function ( nums , k ) {
const n = nums . length ;
k %= n ;
const reverse = ( i , j ) => {
for (; i < j ; ++ i , -- j ) {
[ nums [ i ], nums [ j ]] = [ nums [ j ], nums [ i ]];
}
};
reverse ( 0 , n - 1 );
reverse ( 0 , k - 1 );
reverse ( k , n - 1 );
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 public class Solution {
private int [] nums ;
public void Rotate ( int [] nums , int k ) {
this . nums = nums ;
int n = nums . Length ;
k %= n ;
reverse ( 0 , n - 1 );
reverse ( 0 , k - 1 );
reverse ( k , n - 1 );
}
private void reverse ( int i , int j ) {
for (; i < j ; ++ i , -- j ) {
int t = nums [ i ];
nums [ i ] = nums [ j ];
nums [ j ] = t ;
}
}
}
方法二