LeetCode Top Interview Questions 189. Rotate Array (Java版; Easy)

welcome to my blog

LeetCode Top Interview Questions 189. Rotate Array (Java版; Easy)

题目描述
Given an array, rotate the array to the right by k steps, where k is non-negative.

Example 1:

Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:

Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation: 
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Note:

Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
Could you do it in-place with O(1) extra space?
第一次做; 环状替代法; 不如力扣题解写得简洁; 移动过程有点类似链表反转操作
class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null || nums.length==0)
            return;
        int n = nums.length;
        //小优化
        k = k%n;
        //处理过的元素的个数; 一共需要处理n个元素
        int count = 0;
        //待处理的位置
        int start = 0;
        for(; count<n; start++){
            //待处理的位置
            int i = start;
            //待处理的元素
            int cur = nums[i];
            //下面的操作流程有点类似链表翻转
            int index;
            int next;
            do{
                //save next
                //cur移动到index位置
                index = (i + k) % n;
                //移动元素之前先保存下一个位置的元素
                next = nums[index];

                //execute
                //移动
                nums[index] = cur;

                //update
                //处理过的元素个数++
                count++;
                i = index;
                cur = next;
            }while(i!=start);
        }

    }
}
第一次做; 时间复杂度O(N), 空间复杂度O(1); 三次翻转, 具体见例子; 细节: 处理前先更新k, 令k=k%n
/*
三次反转
例子,Input: [1,2,3,4,5,6,7] and k = 3
反转[0,n-1]后, [7,6,5,4,3,2,1]
反转[0,k-1]后, [5,6,7,4,3,2,1]
反转[k,n-1]后, [5,6,7,1,2,3,4]
*/
class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null || k%nums.length==0)
            return;
        int n = nums.length;
        k = k%n;
        //第一次反转, 反转[0,n-1]
        int left=0, right=n-1;
        while(left<right){
            swap(nums, left++, right--);
        }
        //第二次反转, 反转[0,k-1]
        left=0;
        right=k-1;
        while(left<right){
            swap(nums, left++, right--);
        }
        //第三次反转, 反转[k,n-1]
        left=k;
        right = n-1;
        while(left<right){
            swap(nums, left++, right--);
        }
    }
    public void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}
第一次做; 时间复杂度O(k*N), 空间复杂度O(1); 暴力解法, 每次旋转一个位置, 核心:处理的是位置, 处理顺序[0,n-1], 别理解成处理某个元素; 两个变量pre, cur; 暴力方法虽然慢, 但是要掌握暴力的处理流程
//暴力解法
class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null || k%nums.length==0)
            return;
        int n = nums.length;
        //小小地优化,减少循环次数
        k = k%n;
        //pre记录cur的前一个元素
        int pre, cur;
        //旋转k次
        for(int i=0; i<k; i++){
            //虽然索引都是n-1每一次外循环的pre都不一样
            pre = nums[n-1];
            //处理顺序[0,n-1]
            for(int j=0; j<n; j++){
                cur = nums[j];
                nums[j] = pre;
                pre = cur;
            }
        }
    }
}
第一次做; 时间复杂度O(N), 空间复杂度O(N); 就像循环移位一样; 创建一个等长的数组arr,将nums[0]放在arr的索引k位置, 之后再放nums[1,n-1], arr的索引要取模, 防止越界; 细节: java是值传递, 函数内改变nums不会影响外面的nums; 摘自力扣题解:我们可以用一个额外的数组来将每个元素放到正确的位置上,也就是原本数组里下标为 i 的我们把它放到 (i+k)%数组长度 的位置, 然后把新的数组拷贝到原数组中。
class Solution {
    public void rotate(int[] nums, int k) {
        if(nums==null || k%nums.length==0)
            return;
        int n = nums.length;
        k = k%n;
        int[] arr = new int[n];
        for(int i=0; i<n; i++){
            arr[(i+k)%n] = nums[i];
        }
        //核心:java是值传递, 所以改变nums不会影响外面的nums
        //nums = arr;
        
        for(int i=0; i<n; i++){
            nums[i] = arr[i];
        }
    }
}
力扣题解; 环状替代法; 第一次使用do while循环结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值