【LeetCode---189】旋转数组---双指针

【LeetCode---189】旋转数组---双指针

一、题目

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotate-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

进阶:

  • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
  • 你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

示例1:

输入: nums = [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:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <= 2 * 104
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

二、我的错误解

1、我的思路---跟着范例来的

image-20210923160409593

2、代码

class Solution {
    public void rotate(int[] nums, int k) {
        int sourcePos = 0;//当前的下标,从0开始。
        int targetPos = 0;//目标移动到的地方
        int i=0;//计数器,一共要循环做多少次
        int nextValue=0;//目标移动到的地方的值
        int sourceValue=nums[0];//当前的值,从第一个开始。
        int nextPos = 0;

        for (i=0;i<nums.length;i++){
            //寻找到目标移动到的地方
            targetPos = getTargetPos(sourcePos,k,nums.length);
            //将当前的目标移动到目标位置,并记录目标位置的值。
            nextValue = move(nums,sourceValue,targetPos);
            //记录下一次的sourcePos,该做哪个下标了
            sourcePos = targetPos;
            //sourceValue更新
            sourceValue = nextValue;
        }

    }

    public int getTargetPos(int sourcePos,int step,int length){
        int targetPos = sourcePos + step;
        if(targetPos > length-1)
            targetPos = (targetPos % (length-1))-1;
        
        return targetPos;
    }

    //移动到目标位置,并返回目标位置的值
    public int move(int[] a,int value,int target){
        int temp = 0;
        temp = a[target];
        a[target] = value;
        return temp;
    }
}

3、测试用例通过

image-20210923160502028

4、没有通过的案例

image-20210923160523330

自己debug测试:

image-20210923160657519

发现按照7个的长度,3的步长去移动成功。继续深入debug,是对于判断结果有错误,先跳过我的错误解。下面看官方的解。

三、官方解

1、使用额外的数组

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] newArr = new int[n];
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i];
        }
        System.arraycopy(newArr, 0, nums, 0, n);
    }
}

2、环状替代

这种方法和我的思路类似,下面看一下官方的解清晰的思路。

①思路

image-20210923161555317

②解释与图例

image-20210927161805246

image-20210927161846931

  • 方式一:增加一个计数变量Count,每次一个位置移动成功就加1,当Count=len时候,即可结束循环。

  • 方式二:

    • 思考从0开始便利最终回到0,我们遍历了多少个元素。

      image-20210927162013536

    • image-20210927162051871

    • image-20210927162101064

    • image-20210927162113126

    • image-20210927162121778

③代码实现

public class Solution2 {

    public static void rotate(int [] nums,int k){
        int n = nums.length;
        k = k % n;//移动的step,做处理
        int count = gcd(k,n);//需要多少轮
        for (int start=0;start < count;++start){
            int current = start;
            int prev = nums[start];
            do {
                int next = (current + k) %n;
                int temp = nums[next];
                nums[next] = prev;
                prev = temp;//下一次循环需要用到
                current = next;
            }while (start != current);
        }

    }

    //如果q和r分别是m除以n的商及余数,即m=nq + r,那么m和n的最大公约数等于n和r的最大公约数。
    public static int gcd(int a,int b){
        if (b==0)
            return a;
        return gcd(b,a%b);
    }

}

3、数组反转

①算法解释

image-20210923170444783

②代码实现

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

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

四、思考与反思

​ 可以在我的程序中看到,写了一堆,声明了好多变量,最后自己都不知道该用哪个,以后在设计变量的时候,要在伪代码中写好,尽可能的少声明一些变量来解决问题。并且,写了好多函数,但其实没有什么实质的作用,可以看出思路还是比较混乱,在处理问题的时候,没有考虑周全。一般比如移动的步数,和数组的长度的关系,这是要考虑的,还有什么时候循环截止,循环停止的条件,如果只按照测试用例来写代码,肯定不行,只能通过一个,而在写代码之前就要把所有的情况都考虑进来,这就是思维的差距了。

posted @ 2021-09-27 22:03  DarkerG  阅读(63)  评论(0编辑  收藏  举报