双指针算法:移动零+复写零(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--;
        }
    }
}

提交代码

相关推荐
青少儿编程课堂9 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:折半搜索优化子集枚举(Meet in the Middle)解析
c++·python·算法·bfs·信息学竞赛
wo_jack10 小时前
C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?
数据结构·c++·面试·stl·list
Oneshot11 小时前
DLX(Dancing Links)算法详解:求解数独最快的算法
算法
青少儿编程课堂11 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园连连看解析
c++·python·算法·bfs·信息学竞赛
kongdong12 小时前
Hikyuu | RSI均值回归交易策略实现
算法·均值算法·回归·量化交易·交易策略·hikyuu
小王C语言12 小时前
优选算法:分治-归并排序
算法
zaizai100713 小时前
算法(左程云)1
数据结构
charliejohn13 小时前
计算机考研 408 数据结构 图论-关键路径
数据结构·图论
非优秀程序员1 天前
第05章 播放器大战,暴风、快播与那一夜|《互联网产品恩仇录》
算法