(leetcode初级算法)旋转数组java

旋转数组
给定一个数组,将数组中的元素向右移动 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,2,3,4,5,6,7] k = 3
[5,6,7,1,2,3,4]
会发现其实我们可以从第一位数开始,将它移动到“正确的位置”,例如我们将1移动到4的位置,即将nums[0]移动到nums[0+k],即nums[3],然后将nums[3]同样向后移动k位(越界时区余数),这样移动数组长度的次数后,就将所有数字都放在了“正确的位置”,循环结束

但此时你会发现如果是
k=3
[1,2,3,4,5,6]
[4,5,6,1,2,3]
在此时(nums.length可被k整除),你试着移动两次之后发现,移动数回到了nums[0],首尾发生连接但并没有移动完,但此时继续移动也不对,因为他们在前两次已经移动到正确的位置了,
因此设置flag进行判断,若发生整除循环,则向后错一位,我们从nums[1]再次开始移动。
(想画图来着,手绘板没带回家,以后补图吧=-=)

java:

class Solution {
    public void rotate(int[] nums, int k) {
        // //1.先暴力平移,整体向右移动一步,执行k次
        // int j = 0;
        // int len =nums.length;
        // if(nums.length>0){
        //     while(j
        //         int temp = nums[len-1];
        //         for(int i=len-1;i>0;i--){
        //             nums[i]=nums[i-1];
        //         }
        //         nums[0]=temp;
        //         j++;
        //     }
        // }
        //2.k步错位
        int j=0;
        int temp =0;
        int temp2=nums[0];
        //flag作用是判断当前数组是否k整除并即将开始循环
        int flag=0;
        for(int i=0;i<nums.length;i++){
            int ja=(j+k)%nums.length;
            temp=temp2;
            //如果开始循环(也就是说先前遍历标记ja,已经到达了曾经走过的开头但是并没有完成length次的交换,那么ja+1向后错一位,避免陷入整除循环)
            if(ja==flag){
                temp2=nums[(ja+1)%nums.length];
                nums[ja]=temp;
                j=(ja+1)%nums.length;
                flag++;
            //数组长度不被k整除,一次完整遍历即可结束
            }else{
                temp2=nums[ja];
                nums[ja]=temp;
                j=ja;
            }
                
        }
            
    }
}

你可能感兴趣的:(leetcode算法)