问题描述:
给你一个数组,将数组中的元素向右轮转 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]
原因分析:【这是大佬总结的,在这里谢谢小甜甜大佬】
- 此题可以采用头插法,一个一个的移动。但是有种更加简单的选择数组的方式。
- 我们可以采用翻转的方式,比如12345经过翻转就变成了54321,
- 这样已经做到了把前面的数字放到后面去,但是还没有完全达到我们的要求,
- 比如,我们只需要把12放在后面去,目标数组就是34512,与54321对比发现我们就只需要在把分界线前后数组再进行翻转一次就可得到目标数组了。
- 所以此题只需要采取三次翻转的方式就可以得到目标数组:
- 首先翻转分界线前后数组,再整体翻转一次即可。
- 此题面试常考,大家可以记一下此方法。
- 需要注意的是,本题还有一个小陷阱,题目输入中,如果k大于nums.size了应该怎么办?**
解决方案:
1.如果k大于nums.size了应该怎么办?
举个例子,比较容易想,
例如,1,2,3,4,5,6,7 如果右移动15次的话,是 7 1 2 3 4 5 6 。
所以其实就是右移 k % nums.size() 次,即:15 % 7 = 1
官方没有给出python的方法,因为在python中,列表的切片真的是太灵活了。
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
nums[: ] = (nums[i] for i in range(-(k % len(nums)), len(nums) - k % len(nums)))
这是大佬的代码。【优化后】
至于上述思路中的三次翻转,大佬只用了两次翻转。因为python对列表可以选取,所以不需要整体去翻转,只需要按照k值,截取移动长度,然后在拼接成一个,就可以。
【优化前的代码,理解起来也挺容易的】:
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
nums[: ] = nums[-k % len(nums): ] + nums[: -k % len(nums)]
至于为什么开头的nums要变为nums[ : ] ,是因为:
不写切片相当于nums修改的地址重新指向右边的临时地址,写切片相当于按着切片下标修改值,前者在线上判定里无法AC,线上判定只判定原地地址的情况,不写切片的nums只在函数内有效。
如果换成其他语言,就可以循规蹈矩,按照之前的分析做即可:
1、python【俺自己写的,比较垃圾】
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
if(len(nums)<2):
return
k = k%len(nums)-1
nums[ : ] = nums[::-1]
nums[ : ] = nums[k::-1]+nums[:k:-1]
2、 C++【大佬写的,侵删】
class Solution {
public:
void rotate(vector<int>& nums, int k) {
// 三次翻转搞定
k = k % nums.size();
reverse(nums.begin(), nums.begin() + nums.size() - k);
reverse(nums.begin() + nums.size() - k, nums.end());
reverse(nums.begin(), nums.end());
}
};
3、Java 【大佬写的,侵删】
class Solution {
private void reverse(int[] nums, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
}
}
public void rotate(int[] nums, int k) {
int n = nums.length;
k %= n;
reverse(nums, 0, n - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, n - 1);
}
}
总结:
其实如果单纯用python自带的reverse函数做,其实和其他语言没有区别,
但是如果用python中的切片方法做,那么你得了解足够了解,不然很容易被弄糊涂【比如我】
感谢大佬们在Leecode中的精彩评论,感谢CSDN中各位大哥的博客。
这是一篇博客,让我了解和复习了python切片,十分感谢: