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;
        }
    }
};

 

posted @ 2022-10-07 11:02  WTSRUVF  阅读(15)  评论(0编辑  收藏  举报