LeetCode-探索-初级-数组-旋转数组-java

  旋转数组

给定一个数组,将数组中的元素向右移动 个位置,其中 是非负数。

示例 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) 的原地算法。

题目让我们至少使用三种方法,我们就使用三种方法吧~


方法一:

还记得我们交换两个int的代码吗?

int temp = a1;

a1 = a2;

a2 = temp;

扫描二维码关注公众号,回复: 4706648 查看本文章

是这样吧~

我们以nums=[1, 2, 3, 4, 5, 6, 7],k=3为例

第一次变换:1 2 3 1(4) 5 6 7

第二次变换:1 2 3 1(4) 2(5) 6 7

第三次变换:1 2 3 1(4) 2(5) 3(6) 7

第四次变换:1 2 3 1(4) 2(5) 3(6) 4(7)

我们可以看出:我们需要一个k长度的数组存储中间因为1 2 3覆盖掉的4 5 6;可以看出,在第四次变换中,我们的4又重新派上了用场。

代码如下:

public void rotate(int[] nums, int k) {
        if (k == nums.length || k == 0 || nums.length == 1)
            return ;
        k = k % nums.length;
        int[] tempArray = new int[k];  //store the temp elements
        for (int i = 0; i < k; i++)
            tempArray[i] = nums[i];
        //init tempArray
        int temp = 0;
        int index = 0;
        int tempIndex = 0;
        for (int i = 0; i < nums.length; i++) {
            index = (i + k) % nums.length;
            temp = nums[index];
            nums[index] = tempArray[tempIndex];
            tempArray[tempIndex] = temp;
            tempIndex = (tempIndex + 1) % k;
        }
    }

方法二:

在第一种方法中,我们需要不停变换之前的临时数组tempArray中的元素,好的,我不想变。

我要考虑另外的思路。

还是上面的例子nums=[1, 2, 3, 4, 5, 6, 7],k=3

初始状态:1 2 3 4 5 6 7

最终状态:5 6 7 1 2 3 4

是不是发现了些什么?

最后的三个元素移动到了前面,前面的元素移动到了后面

像极了将前面的元素删除之后再插入到后面(在顺序表中)【但是我并没有这样写】

代码如下:

    public void rotate3(int[] nums, int k) {
        k = k % nums.length;
        if (k == 0)
            return ;
        int[] temp = new int[k];
        int index = 0;
        for (int i = nums.length - k; i < nums.length ; i ++)
            temp[index ++] = nums[i];
        //end store elements
        for (int i = nums.length - k - 1 ; i >= 0 ; i --)
            nums[i+ k] = nums[i];
        for (int i = 0 ; i < k ; i ++)
            nums[i] = temp[i];
    }

方法三:

emm,为什么要利用一个数组存储?不能用一个int的量吗?

可以。

仍然是上面的例子:nums=[1, 2, 3, 4, 5, 6, 7],k=3

我们进行如下的变换:

5(1) 6(2) 7(3) 1(4) 2(5) 3(6) 4(7)

大变换是从nums[0] to nums[3] to nums[6] to nums[2] to nums[5] to nums[1] to nums[4] to nums[0](end)

但是这并不绝对,因为有可能出现nums=[1, 2, 3, 4, 5, 6],k=2的情况,如果还是仅仅从0开始,就会发生如下情况

nums[0] to nums[2] to nums[4] to nums[0](end)

无法完成一次整体的循环

针对这种情况,就要依次从0-k-1作为起点进行k次大的变换

代码如下:

    public void rotate2(int[] nums, int k) {
        k = k % nums.length;
        if (k == 0)
            return ;
        BitSet bitSet = new BitSet(nums.length);
        int prev;
        int next;
        int nextIndex = 0;
        for (int i = 0 ; i < k ; i ++) {
            next = nums[i];  //每一次开始起始的值都要发生变化
            for (int index = i ; !bitSet.get(index) ; index = nextIndex) {
                nextIndex = (index + k) % nums.length;  //下一个位置
                prev = nums[nextIndex];
                nums[nextIndex] = next;
                next = prev;
                bitSet.set(index);  //标记当前位数
            }
        }
    }

bitset用于记录那些值是被替换过的,下一次进行循环的时候就不会重复操作。

猜你喜欢

转载自blog.csdn.net/jdie00/article/details/84324100