189. 轮转数组
189. 轮转数组
给你一个数组,将数组中的元素向右轮转 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)
的 原地 算法解决这个问题吗?
解析:
设起点为下标位置0,临时变量保存起点的值,每次计算出是哪个位置的值要放到当前位置,然后直接放即可
遍历数组,以每个i为起点进行一次上述操作,那如何记录当前下标已经执行过了呢?
每次执行操作之前,先遍历一遍这个环,如果里面有小于起点的下标,则说明已经当前下标已经操作完了
当然这样为O(n^2),用cnt表示当前总共已经操作了多少个数,每次用cnt1记录当前操作的数量
cnt += cnt1,如果cnt == n,则说明数组完成操作
class Solution { public: bool check(int s, int n, int k) { int nx = (s + k) % n; while(nx > s) { nx = (nx + k) % n; } if(nx < s) return 0; return 1; } void rotate(vector<int>& nums, int k) { int n = nums.size(); k = k % n; int cnt = 0; for(int i = 0; i < nums.size(); i++) { if(!check(i, n, k)) continue; int cnt1 = 1; int orig = nums[i]; int prex = i - k; int lastx = i; if(prex < 0) prex += n; while(prex != i) { cnt1++; nums[lastx] = nums[prex]; lastx = prex; prex -= k; if(prex < 0) prex += n; } nums[lastx] = orig; cnt += cnt1; if(cnt == n) break; } } };
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。