算法之双指针系列(一)

题目

力扣 283 题:移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意,必须在不复制数组的情况下原地对数组进行操作。

思路

可以将这个数组划分为三块区域:

  1. 非零数字区域
  2. 全为 0 的区域
  3. 未处理区域

数组大小为 n,可以定义两个变量 cur = 0、dest = -1:

  • 0 ~ dest 表示非零区域
  • dest + 1 ~ cur - 1 表示零区域
  • cur ~ n - 1 表示未处理区域

由 cur 对数组进行遍历(每次都 ++)。当遇到的数是 0 时,零区域需要扩大,此时只执行 cur++;

若遇到的数非 0,则执行 dest++,此时非零区域变大。这时 dest 指向的是一个 0,而 cur 指向非 0,于是交换 nums[cur] 与 nums[dest]。交换后,dest 指向的就是非零元素,而 cur 指向 0。

参考代码

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int cur = 0, dest = -1;
        while (cur < nums.length) {
            if (nums[cur] != 0) {
                dest++;
                int tmp = nums[cur];
                nums[cur] = nums[dest];
                nums[dest] = tmp;
            }
            cur++;
        }
    }
}

题目

力扣 1089 题:复写零

给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。请对输入的数组就地进行上述修改,不要从函数返回任何东西。

思路

从前往后开始复写 0,会导致被 0 覆盖的数字很难被记录下来,不如「正难则反」,从后往前开始复写 0。我们只需要记录原数组从前往后复写时,能复写到第几位数字就可以了。

定义两个变量:cur = 0、dest = -1。

  • 0 ~ cur - 1 表示已经统计好长度的原数组元素
  • cur 表示正在统计的原数组元素
  • dest 表示复写到哪一位
  • n 表示数组大小

先用 while (cur < n) 以 cur++ 的形式遍历数组:当 arr[cur] == 0 时,dest += 2,因为 0 要写两次,一次占用两个位置;否则 arr[cur] != 0 时,dest++。每次循环结束后 cur++。

同时要做特殊情况处理:在 dest 接近数组末尾时,dest 可能等于 n - 1,或者直接越界等于 n。此时对 dest == n 做特殊处理------因为 dest 能等于 n,是因为 cur 最后一次处理时 arr[cur] == 0,所以 dest += 2 后 dest == n。此时只需要令 arr[n - 1] = 0,再执行 cur--、dest -= 2,特殊情况即处理完成。

最后则是 while (cur >= 0) 从后往前循环:当 arr[cur] == 0 时,连续两次执行 arr[dest--] = 0,并执行 cur--;否则执行 arr[dest--] = arr[cur--]。

参考代码

java 复制代码
class Solution {
    public void duplicateZeros(int[] arr) {
        int n = arr.length;
        int cur = 0, dest = -1;
        while (cur < n) {
            if (arr[cur] == 0) {
                dest += 2;
            } else {
                dest++;
            }
            if (dest >= n - 1) {
                break;
            }
            cur++;
        }
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        while (cur >= 0) {
            if (arr[cur] == 0) {
                arr[dest--] = 0;
                arr[dest--] = 0;
            } else {
                arr[dest--] = arr[cur];
            }
            cur--;
        }
    }
}
相关推荐
十二18 分钟前
【洛谷题解】P1083 [NOIP 2012 提高组] 借教室(二分答案 + 差分)
数据结构·c++·算法·蓝桥杯
小此方1 小时前
[算法实战论:动态规划]回文串问题的dp解法,回文串问题的母题,以及以此为基础的派生题
算法·动态规划
Pniubi2 小时前
力扣560.和为k的子数组
算法·leetcode·职场和发展
D e re k ZH2 小时前
C++ 从零入门(一):基础语法与程序结构
数据结构·c++·算法
Pniubi3 小时前
力扣438.找到字符串中所有字母异位词
算法·leetcode·职场和发展
東隅已逝,桑榆非晚5 小时前
算法6. 双指针法-查找总价格为目标的两个商品
c++·学习·算法
Eyfcom6 小时前
〖物联网终端实战 01〗UWB 室内高精度定位:仓储 AGV 与人员的厘米级轨迹追踪
物联网·算法·物流系统·快递系统·跨境物流快递系统·物联网终端实战
bro_Java6666 小时前
《排序的底层逻辑:比较、交换与分治》
java·算法·排序算法
爱喝雪碧的可乐7 小时前
MATLAB
开发语言·算法·matlab