LeetCode189:旋转数组

题目描述

给定一个数组,将数组中的元素向右移动 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)的话,可以利用一个辅助数组(把数组的变化看成两部分,左边的部分右移,右边的部分左移

时间复杂度O(n),空间复杂度O(n)

代码如下:

class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null||nums.length<2||(k=k%nums.length)==0){
            return;
        }
        //left存需要往右移的左半部分数组
        int[] left = Arrays.copyOfRange(nums,0,nums.length-k);
        for(int i=0;i<k;i++){
            nums[i] = nums[i+nums.length-k];
        }
        for(int i=k;i<nums.length;i++){
            nums[i] = left[i-k];
        }
        return;
    }
}

解法二

将数组旋转k次,每次旋转1个位置

时间复杂度O(n*k),空间复杂度O(1)

代码如下:

class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null||nums.length<2||(k=k%nums.length)==0){
            return;
        }
        while(k>0){
            rotateForOne(nums);
            k--;
        }
        
    }
    private void rotateForOne(int[] nums){
        int pre = nums[0];
        for(int i=1;i<nums.length;i++){
            int temp = nums[i];
            nums[i] = pre;
            pre = temp;
        }
        nums[0] = pre;
    }
}

解法三

直接把元素放到它最后应该在的位置(我们需要把被替换的数字保存在变量 temp 里面。然后,我们将被替换数字temp放到它正确的位置,并继续这个过程 n次)。这有个问题就是可能在没有遍历所有数字的情况下回到出发数字,这就需要加一个判断,如果出现这个情况,就从下一个数字开始,重复上述过程,直到数组中的所有元素都被移动。

时间复杂度O(n),空间复杂度O(1)

代码如下:

class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null||nums.length<2||(k=k%nums.length)==0){
            return;
        }
        int count = 0;//移动的次数,当count==nums.length时,移动结束
        for(int i=0;count<nums.length;i++){
            int current = i;
            int pre = nums[i];
            do{
                current = (current+k)%nums.length;
                int temp = nums[current];
                nums[current] = pre;
                pre = temp;
                count++;
            }while(current!=i);
        }
    }
}

解法四

这个解法是三次反转,主要也利用了解法一中提到的特点——(把数组的变化看成两部分,左边的部分右移,右边的部分左移
在这里插入图片描述
算法思路如下图:
在这里插入图片描述

时间复杂度O(n),空间复杂度O(1)

代码如下:

class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null||nums.length<2||(k=k%nums.length)==0){
            return;
        }
        reverse(nums,0,nums.length-1);
        reverse(nums,0,k-1);
        reverse(nums,k,nums.length-1);
        
    }
    private void reverse(int[] nums,int start,int end){
        while(start<end){
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }

}

图片来自这里

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章