leetcode189 轮转数组

文章目录

  • 1.前言
  • 2.解法
    • 2.1 中间数组
    • 2.2 冒泡轮转
    • 2.3 分块反转
  • 3.原题


1.前言

写博客监督自己,至少保证每天一条,解法不一定全,也不一定是最好的,仅供参考。


2.解法

2.1 中间数组

最简单的想法就是新建一个数组,然后复制

System.arraycopy(int[] arr, int star,int[] arr2, int start2, length);
//				被复制数组	开始下标	目标数组	开始放入位置		复制个数
//写的第一个版本,测试用例 [-1] k=2 报错,nums.length=1,1-2=-1 导致数组索引越界
class Solution {
    public void rotate(int[] nums, int k) {
        //添加后通过测试
        if(k > nums.length){
            k = k % nums.length;
        }
        
        int[] newArr = new int[nums.length];
        System.arraycopy(nums, 0, newArr, 0, nums.length);
        System.arraycopy(newArr, nums.length - k, nums, 0, k);
        System.arraycopy(newArr, 0, nums, k, nums.length - k);
    }
}

或者

class Solution {
    public void rotate(int[] nums, int k) {
        if(k > nums.length){
            k = k % nums.length;
        }
        int[] newArr = new int[nums.length];
        for(int i = 0; i < k; i++){
            newArr[i] = nums[nums.length - k + i];
        }
        for(int i = k; i < nums.length; i++){
            newArr[i] = nums[i - k];
        }

        System.arraycopy(newArr, 0, nums, 0, nums.length);
    }
}

时间复杂度O(n)

空间复杂度O(n)


2.2 冒泡轮转

每次向右轮转的过程中,类似冒泡排序

输入: nums = [1,2,3,4], k = 1
向右轮转 1 步: [1,2,3,4]——》[1,2,4,3]-》[1,4,2,3]-》[4,1,2,3]
class Solution {
    public void rotate(int[] nums, int k) {
        for(int i = 0; i < k; i++){
            for(int j = nums.length - 1; j > 0; j--){
                int temp = nums[j];
                nums[j] = nums[j - 1];
                nums[j - 1] = temp;
            }
        }
    }
}

时间复杂度O(n*k)

空间复杂度O(1)

提交时,有一个测试用例为new int[100000],k=54944时,运行超时


2.3 分块反转

举例:1,2,3,4,5,6 k=2

  1. 分成两部分1234和56
  2. 轮转1234——》4321 变成432156
  3. 轮转56——》65 变成432165
  4. 轮转整个数组 变成561234
class Solution {
    public void rotate(int[] nums, int k) {
        if(k > nums.length){
            k = k % nums.length;
        }
        int l = nums.length - k;
        reverse(nums, 0, l - 1);
        reverse(nums, l, nums.length - 1);
        reverse(nums, 0, nums.length - 1);
    }

    private void reverse(int[] nums, int left, int right){
        while(left < right){
            int temp = nums[left];
            nums[left++] = nums[right];
            nums[right--] = temp;
        }
    }
}

时间复杂度O(n)

空间复杂度O(1)


3.原题

给定一个整数数组 nums,将数组中的元素向右轮转 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)原地 算法解决这个问题吗?

你可能感兴趣的:(算法,leetcode,数据结构)