题目主要信息:
- 一个长度为的数组,将数组整体循环右移个位置(可能大于)
- 循环右移即最后个元素放在数组最前面,前个元素依次后移
- 不能使用额外的数组空间
举一反三:
学习完本题的思路你可以解决如下题目:
方法:三次翻转(推荐使用)
思路:
循环右移相当于从第个位置开始,左右两部分视作整体翻转。即abcdefg右移3位efgabcd可以看成AB翻转成BA(这里小写字母看成数组元素,大写字母看成整体)。既然是翻转我们就可以用到reverse函数。
具体做法:
- step 1:因为可能大于,因此需要对取余,因为每次长度为的旋转数组相当于没有变化。
- step 2:第一次将整个数组翻转,得到数组的逆序,它已经满足了右移的整体出现在了左边。
- step 3:第二次就将左边的个元素单独翻转,因为它虽然移到了左边,但是逆序了。
- step 4:第三次就将右边的个元素单独翻转,因此这部分也逆序了。
图示:
Java代码实现:
public class Solution {
public int[] solve (int n, int m, int[] a) {
//取余,因为每次长度为n的旋转数组相当于没有变化
m = m % n;
//第一次逆转全部数组元素
reverse(a, 0, n - 1);
//第二次只逆转开头m个
reverse(a, 0, m - 1);
//第三次只逆转结尾m个
reverse(a, m, n - 1);
return a;
}
//反转函数
public void reverse(int[] nums, int start, int end){
while(start < end){
swap(nums, start++, end--);
}
}
//交换函数
public void swap(int[] nums, int a, int b){
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
}
C++代码实现:
class Solution {
public:
vector<int> solve(int n, int m, vector<int>& a) {
//取余,因为每次长度为n的旋转数组相当于没有变化
m = m % n;
//第一次逆转全部数组元素
reverse(a.begin(), a.end());
//第二次只逆转开头m个
reverse(a.begin(), a.begin() + m);
//第三次只逆转结尾m个
reverse(a.begin() + m, a.end());
return a;
}
};
Python实现代码:
class Solution:
def solve(self , n: int, m: int, a: List[int]) -> List[int]:
#取余,因为每次长度为n的旋转数组相当于没有变化
m = m % n
#第一次逆转全部数组元素
a.reverse()
b = a[:m]
#第二次只逆转开头m个
b.reverse()
c = a[m:]
#第三次只逆转结尾m个
c.reverse()
a[:m] = b
a[m:] = c
return a
复杂度分析:
- 时间复杂度:,三次reverse函数的复杂度都最坏为
- 空间复杂度:,没有使用额外的辅助空间