题目:给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入:[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:
输入: [-1,-100,3,99]
和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
说明:
- 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
- 要求使用空间复杂度为 O(1) 的原地算法。
解:
这道题,恕我直言,第一次见(谁让我跨专业呢),没想法,学就是了:
学到了一种方法:
1、数组先倒过来,如题[7,6,5,4,3,2,1],这样倒数k个要移动的数就是现在正数k个数;
2、把数组分开两段:s[0,length-1]=s[0,length-1-k]+s[length-1-k,length-1](正序表示),即[7,6,5]+[4,3,2,1](倒序表示)
3、分别再倒回去,即[5,6,7]+[1,2,3,4]
再说一下细节:
k不一定是<=len(nums),所以先k%len(nums),避免没必要的周期移动。
python既可以写函数,也可以直接替换(list特性),不过两个占用内存一样的,而且耗时写函数的会快一点。
附code:
(1/4)C++: 用时44ms,耗用9.6MB内存
class Solution {
public:
void rotate(vector<int>& nums, int k) {
k=k%nums.size();
std::reverse(nums.begin(),nums.end());
std::reverse(nums.begin(),nums.begin()+k);
std::reverse(nums.begin()+k,nums.end());
}
};
(2/4)C++:评论区看到的,用时28ms,耗用9.5MB内存(快一点)
class Solution {
public:
void rotate(vector<int> &nums, int k)
{
k %= nums.size();
if (k == 0 || nums.size() == 1)
return;
int begin = 0, ro = nums[0], ro_idx = 0, tmp, next;
for (int i = 0; i < nums.size(); i++)
{
next = (ro_idx + k) % nums.size();
tmp = nums[next];
nums[next] = ro;
if (next == begin)
{
begin++;
ro_idx = begin;
ro = nums[begin];
continue;
}
ro_idx = next;
ro = tmp;
}
}
};
求助:循环中if这一段没看懂有什么用?有前辈给我解释一下嘛
(3/4)python3:用时68ms,耗用13.5MB(果然比C++慢啊)
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
l=len(nums)
nums[:]=nums[l-k:]+nums[:l-k]
(4/4)python3:80ms,13.5MB(上文的方法的python实现)
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def rev(start,end,s):
while start<end:
s[end],s[start]=s[start],s[end]
start+=1
end-=1
l=len(nums)
rev(l-k%l,l-1,nums)
rev(0,l-k%l-1,nums)
rev(0,l-1,nums)