力扣-Leetcode-初级算法-旋转数组

旋转数组

第一次尝试

思路

数组右移动K个位置,可以划分为数组移动K次,每次移动一位,如果数组移动一位的话,只需要将最后一个放到开头,剩下的后移一位就行

代码

class Solution {
    public void rotate(int[] nums, int k) {
        for (int i = 0; i < k; i++) {
            rightMove(nums);
        }
    }
    
    // 右移一位
    public void rightMove(int[] nums) {
        int end = nums[nums.length - 1];
        for (int i = 0; i < nums.length - 1; i++) {
            nums[nums.length - 1 - i] = nums[nums.length - 2 - i];
        }
        nums[0] = end;
    }
}

提交结果

小结

每次移动一位速度实在太慢,这时候想,如果可以提前计算好移动k位后的位置,一次移动到位,就不用反复移动数组了

 

第二次尝试

思路

使用 (数组下标+移动位数) % 数组长度 计算出数组位置,然后new出一个新数组,依次将数放到新数组计算出的位置

代码

class Solution {
    public void rotate(int[] nums, int k) {
        int[] ops = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            int index = (k+i)%nums.length;
            System.out.println(i+":"+index);
            ops[index] = nums[i];
        }
        // java是引用的,所以不可以直接将数组赋值过去,需要将数据拷贝到源数组上面
        System.arraycopy(ops,0,nums,0,nums.length);
    }
}

 提交结果

 

小结

速度有所提升,但是还是不大,每次都要计算下标,而且重新new空间了,内存消耗增加了

第三次尝试

思路

观察上面的图可以看出,最后移动的结果,就是数组一分为二,然后将前后结果换过来,如果假设k不超过数组长度,那么分界线的下表就是k,按照求余数的方法,如果k超过数组长度,k mod 数组长度 也就是分界线下标

计算出下标,就可以拷贝,这期间需要一个临时个数组,保存后半部分数据,然后将前半部分拷贝到后半部分,临时数组数据拷贝到前半部分,这里就和连个数字交换值一样,需要借助第三个数字。

代码

class Solution {
    public void rotate(int[] nums, int k) {
        int middle = k % nums.length;
        int[] temp = new int[middle];
        System.arraycopy(nums,nums.length - middle,temp,0,middle);
        System.arraycopy(nums,0,nums,middle,nums.length - middle);
        System.arraycopy(temp,0,nums,0,temp.length);
    }
}

提交结果

小结

惊人的发现执行用时超越100%超越,完美,相比于前两个的,内存消耗也降低了,但是,还是new了新数组,使用了新数组

第四次尝试

思路

在这个图我们可以看出,如果不使用临时数组拷贝的话,可以想到使用翻转,前部分翻转,后部分翻转,整体翻转

代码

class Solution {
    public void rotate(int[] nums, int k) {
        int middle = k % nums.length;
        reverse(nums,0,nums.length - middle - 1);
        reverse(nums,nums.length - middle,nums.length - 1);
        reverse(nums,0,nums.length - 1);
    }

    public void reverse(int[] nums,int begin,int end) {
        int ops = -1;
        while (begin < end) {
            ops = nums[begin];
            nums[begin] = nums[end];
            nums[end] = ops;
            begin ++;
            end --;
        }
    }
}

提交结果

小结

哈哈哈,效率相同,但是内存消耗变大了,似乎多了几个变量

总结

步步为营,一步一步提高效率,System.arraycopy 方法速度非常快,比一个一个赋值快多了

 

burybell@163.com

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值