数组-旋转数组

转载请注明出处 http://blog.csdn.net/qq_31715429/article/details/80272086
本文出自:猴菇先生的博客

给定一个数组,将数组中的元素向右移动 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) 的原地算法。

1.首先最容易想到的:

class Solution {
    public void rotate(int[] nums, int k) {
        k = k % nums.length;//取余是为了旋转好几圈的情况
        if (k == 0) {
            return;
        }
        while (k > 0) {
            int temp = nums[nums.length - 1];
            for (int i = nums.length - 1; i > 0; i--) {
                nums[i] = nums[i - 1];
            }
            nums[0] = temp;
            k--;
        }
    }
}

两层循环,第一层while相当于一步一步往右移,移了几次;第二层for相当于把数组的每个元素挨个移。for里倒序循环,从倒数第二位起依次赋值给前一位,用temp变量存储最末位的值赋给第0位。
这也是我能唯一想到的解法,但是这个解法运行后消耗了130ms。。

2.这个是别人的答案,运行只需要1ms。。

public class Solution {
    public void rotate(int[] nums, int k) {
        if(nums == null || nums.length == 0 || k % nums.length == 0)
            return;

        int turns = k % nums.length;
        int middle = nums.length - turns;

        reverse(nums, 0, middle-1); // reverse left part
        reverse(nums, middle, nums.length-1); // reverse right part
        reverse(nums, 0, nums.length-1); // reverse whole part 
    }

    public void reverse(int[] arr, int s, int e) {
        while(s < e) {
            int temp = arr[s];
            arr[s] = arr[e];
            arr[e] = temp;

            s++;
            e--;
        }
    }
}

大体意思好像是翻转翻转再翻转,反正我是没看懂。。

3.最最粗暴的,执行0ms什么鬼

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

旋转数组说白了就是把第k位的左右两边掉个个,比如从[1,2,3,4,5] -> [4,5,1,2,3],往右移2位就是把4,5放到前面,1,2,3放到后面。
System.arraycopy()用来实现数组之间的复制

/**
 * src:源数组
 * srcPos:源数组要复制的起始位置
 * dest:目的数组
 * destPos:目的数组放置的起始位置
 * length:复制的长度
 */
public static void (Object src, int srcPos, Object dest, 
                    int destPos, int length)

用到这里刚好合适:先把nums的k位往后的后半段copy到nums1的前半段,再把nums的k位往前的前半段copy到nums1的后半段,再整个吧nums1复制给nums。
不得不佩服啊,LeetCode刷题任重而道远。

猜你喜欢

转载自blog.csdn.net/qq_31715429/article/details/80272086