双指针算法:移动零+复写零(Java)

双指针算法介绍

双指针算法一般分为左右指针和同向指针。

左右指针就是一个指针从数组的最左端出发,另一个指针从数组的最右端出发,直到两个指针相遇或是错开时结束移动或是跳出循环。基于这个操作我们可以解决许多看似困难实则简单的题目,如将数组内容分成左右两个部分

同向指针为两个指针朝同一个方向进行移动,两个指针或是移动速度不一致,或是起点不一致,在数组上或是链表上移动, 此方法对于解决环形链表或是数组有很大帮助。


283. 移动零 - 力扣(LeetCode)

点击题目可跳转到力扣页面

题目分析

题目要求我们把数组中所有的零移动到数组的末尾,同时保持其他元素的相对位置不发生变化,同时要在不复制数组的情况下完成。

我们可以理解为,题目要我们把数组中,零的部分放在右边,非零部分在保存相对顺序的情况下放在数组的左端,这样数组就分成了两个部分:!0|0,这是一个双指针算法典型的用法。

题目解答

定义两个指针:left=0,right=0;(假设数组为num)

若num.lengrh==1,直接返回num;

若num.lengrh()!=1:

循环left指针移动;

若numleft==0,不操作,left++;

若numleft!=0,交换数组元素numright和numleft,left++,right++;

注:这样right和left相当于一条分界线,!0|right|0|left|未处理数

若left>num.len,退出循环

此时,数组的左端均为非零数,右端均为零,同时也可以保持非零数直接的顺序没有发生改变

代码实现(Java)

复制代码
class Solution {
    public void moveZeroes(int[] nums) {
         if(nums==null){
            return;
        }
        int cur=0;
        int dest=0;
        while (cur<nums.length){
            if(nums[cur]==0){
                cur++;
            }else {
                //交换
                int tmp=nums[cur];
                nums[cur]=nums[dest];
                nums[dest]=tmp;
                dest++;
                cur++;
            }
        }
    }
}

提交代码

1089. 复写零 - 力扣(LeetCode)

题目分析

题目分析

题目要求我们将数组上原有的零复写一遍,将其余元素往右移动,并且不要超过原数组长度,若我们按正常顺序从前往后,遇到零就将下一个元素改为零的话,后面的元素就会被零覆盖,无法进行下去,不妨我们换个思路,从后往前开始复写,这样前一个元素就不会因为被赋值为零而丢失。因此我们需要先找到最后一个需要复写的位置。

题目解答

  • 定义两个指针:dest=0,cur=0;
  • 循环cur,退出循环:(cur < n)
  • 若cur=0,dest向前走两步,cur向前走一步
  • 若cur!=0,dest向前走一步,cur向前走一步
  • 若是dest>=arr.length-1,break;
  • 出循环,处理边界:若dest>arr.length-1,arr.length-1赋值为0,dest赋值为arr.length-2,cur赋值为cur-1;若dest=arr.length-1,dest赋值为零,cur--;dest--;
  • 循环
  • 若cur==0,arr.dest--=0;arr.dest--=0;cur--;
  • 若cur!=0,arr.dest--=arrcur--;
  • 当cur<0时,退出循环

代码实现(Java)

复制代码
class Solution {
    public void duplicateZeros(int[] arr) {
         //找到最后一个复写的数字
        int cur=-1;
        int dest=-1;
        while (dest<arr.length-1){
            //要先判断dest是否越界,才能cur++
            cur++;
            if(arr[cur]==0){
                dest+=2;
            }else {
                dest++;
            }

        }
        //开始复写
        //处理dest越界情况
        if (dest>arr.length-1){
            dest=arr.length-1;
            arr[dest--]=0;

            cur--;
        }
        while (cur>=0){
            if(arr[cur]==0){
                arr[dest]=0;
                dest--;
                arr[dest]=0;
                dest--;
            }else {
                arr[dest]=arr[cur];
                dest--;
            }
            cur--;
        }
    }
}

提交代码

相关推荐
和芯星通unicore1 小时前
卫星信号消失的地方,定位如何继续?——解密和芯星通DR 航位推算算法
人工智能·算法·gnss·智能驾驶gnss模块
邵奈一2 小时前
让WorkBuddy用上OpenCode免费模型:Magpie小白教程
算法
人工智能培训2 小时前
边缘AI与大模型轻量化:让智能跑进每一个终端
大数据·人工智能·算法·重构·生活
lengxuenong3 小时前
树状数组 · 信息学学习手册3-优化LIS
c++·学习·算法
动词ing3 小时前
【题目练习】外观数列
算法
余额瞒着我当琳3 小时前
C++11,发展历史浅谈,初始化列表和对象初始化,右值引用和移动语义
java·开发语言·c++·算法
suhan3 小时前
【数据结构】六、图:4.图的遍历(深度优先算法DFS、广度优先算法BFS)
数据结构·算法·排序算法
suhan3 小时前
【数据结构】六、图:3.十字链表、邻接多重表、边集数组
数据结构·算法·排序算法