双指针算法--移除元素、删除有序数组中的重复项、合并两个有序数组

一、移除元素

1.题目

链接:https://leetcode.cn/problems/remove-element/description/

2.解法

定义两个整形变量leftright
left指针:标记有效元素的末尾(新数组索引)
right指针:遍历整个数组,查找有效元素

让它们同时指向数组的首元素即left = 0, right = 0;,让right运用循环while遍历数组元素,while执行条件为right < numsSize(数组长度),让nums[right]val比较,如果nums[right] != val,让nums[left] = nums[right] ,同时让left++,循环结束return left;(有效元素个数)

c 复制代码
int removeElement(int* nums, int numsSize, int val) {
    int left = 0;   // 左指针:标记有效元素的末尾(新数组索引)
    int right = 0;  // 右指针:遍历整个数组,查找有效元素
    
    // 右指针遍历完所有元素则结束
    while(right < numsSize)
    {
        // 找到不等于val的有效元素
        if(nums[right] != val)
        {
            // 将有效元素填充到左指针位置,左指针后移(扩大有效区间)
            nums[left++] = nums[right];
        }
        // 无论是否找到有效元素,右指针继续向后遍历
        right++;
    }
    
    // 左指针的值即为有效元素个数(新数组长度)
    return left;
}

代码还可以优化,若 left == right,说明当前元素本就该保留,无需赋值,直接移动双指针即可;只有当 left < right 时,才需要将 right 指向的有效元素覆盖到 left 位置,避免重复赋值。

c 复制代码
int removeElement(int* nums, int numsSize, int val) {
    int left = 0;   // 左指针:指向新数组下一个待填充位置(有效元素边界)
    int right = 0;  // 右指针:遍历原始数组寻找有效元素(不等于val的值)
    
    // 右指针遍历完所有元素则结束循环
    while (right < numsSize) 
    {
        // 当右指针找到有效元素(不等于val)时
        if (nums[right] != val) 
        {
            // 优化点:仅当左右指针不重叠时才赋值
            // 避免同一位置重复写入相同值(如数组开头无val时)
            if (left != right) 
            {
                nums[left] = nums[right];  // 将有效元素移到左指针位置
            }
            left++;  // 左指针后移,扩大有效元素区间
         }
        right++;  // 无论是否找到有效元素,右指针继续向后遍历
    }
    
    // 左指针的值即为有效元素的个数(新数组长度)
    return left;
}

二、删除有序数组中的重复项

1.题目

https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/

2.解题

  1. 定义两个整形变量leftright
    left指针:标记有效元素的末尾(新数组索引)
    right指针:从第2个元素开始寻找更大的新元素(因数组有序)
  2. right运用循环while遍历数组元素,while执行条件为right < numsSize(数组长度)
  3. if (nums[right] > nums[left]) left++,将新元素放到left指针位置
  4. 考虑数组只有一位元素的情况,这种情况就不需要任何操作直接返回原数组大小即可
  5. 循环结束return left + 1;(有效元素个数)
c 复制代码
int removeDuplicates(int* nums, int numsSize) {
    // 边界优化:空数组或只有一个元素时,直接返回原长度(无重复可删)
    if (numsSize <= 1) 
    {
        return numsSize;
    }
    
    int left = 0;   // 左指针:标记当前不重复元素的最后位置
    int right = 1;  // 右指针:从第2个元素开始寻找更大的新元素(因数组有序)
    
    while (right < numsSize) 
    {
        // 若右指针找到更大元素(即新的不重复元素)
        if (nums[right] > nums[left]) 
        {
            // 左指针前移后,将新元素放到左指针位置(合并操作,更紧凑)
            nums[++left] = nums[right];
        }
        right++;  // 右指针继续遍历
    }
    
    // 左指针索引+1即为不重复元素的个数
    return left + 1;
}

三、合并两个有序数组

1.题目

https://leetcode.cn/problems/merge-sorted-array/description

2.解题

  1. 输入:两个非递减序数组nums1(长度m+n,前m个有效元素)和nums2(长度n,全为有效元素)。

    目标:将nums2合并到nums1中,使合并后的nums1仍保持非递减序,原地修改(不使用额外数组)。

  2. 若从数组开头合并(正向遍历),nums1的有效元素可能被nums2的元素覆盖,导致数据丢失。可以使用逆向遍历(从末尾开始合并)。利用nums1末尾的n个预留空间,从后往前填充较大元素,避免覆盖有效数据。

  3. 定义三个指针:

    l1:指向nums1有效元素的末尾(初始值m-1)。

    l2:指向nums2有效元素的末尾(初始值n-1)。

    l3:指向nums1中待填充的位置(初始值(m+n)-1,即数组最后一位)。

  4. 逆向合并核心逻辑:

    比较nums1[l1]nums2[l2]的大小,取较大值放入nums1[l3]

    对应指针左移(l1--l2--),同时填充位置左移(l3--)。

    循环直到l1或l2遍历完(即其中一个数组的元素全部合并)。

  5. 处理剩余元素:
    若nums2还有剩余元素(l2 >= 0),说明nums1的元素已全部合并,直接将nums2剩余元素依次填充到nums1的前端(l3继续左移)。
    若nums1有剩余元素(l1 >= 0),无需处理,因为它们本就处于nums1的前端,且已有序。

c 复制代码
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int l1 = m - 1;    // 指向nums1有效元素的末尾(从后往前遍历)
    int l2 = n - 1;    // 指向nums2有效元素的末尾(从后往前遍历)
    int l3 = nums1Size - 1;  // 指向nums1的最终填充位置(从末尾开始往前填充)

    // 双指针逆向遍历,每次选择两个数组当前末尾的较大元素,填充到nums1末尾
    while (l1 >= 0 && l2 >= 0) 
    {
        // 比较nums1和nums2当前末尾元素,取较大值放入nums1的填充位置
        if (nums1[l1] >= nums2[l2]) 
        {
            nums1[l3--] = nums1[l1--];  // nums1的元素更大,填充后l1和l3均左移
        } else {
            nums1[l3--] = nums2[l2--];  // nums2的元素更大,填充后l2和l3均左移
        }
    }

    // 若nums2还有剩余元素(nums1已遍历完),直接将剩余元素填充到nums1前端
    // (nums1剩余元素已在正确位置,无需处理)
    while (l2 >= 0) 
    {
        nums1[l3--] = nums2[l2--];
    }
}
相关推荐
YuanDaima204819 小时前
二分查找基础原理与题目说明
开发语言·数据结构·人工智能·笔记·python·算法
阿Y加油吧19 小时前
两道中等 DP 题拆解:打家劫舍 & 完全平方数
算法·leetcode·动态规划
七颗糖很甜19 小时前
python实现全国雷达拼图数据的SCIT风暴识别
python·算法·scipy
B325帅猫-量子前沿技术研究所20 小时前
PSD和FFT的关系
人工智能·算法
闻缺陷则喜何志丹20 小时前
【排序】P6149 [USACO20FEB] Triangles S|普及+
c++·算法·排序·洛谷
avocado_green21 小时前
【LeetCode】90. 子集 II
算法·leetcode
tankeven21 小时前
HJ178 【模板】双指针
c++·算法
君义_noip21 小时前
信息学奥赛一本通 4131:【GESP2506六级】学习小组 | 洛谷 P13015 [GESP202506 六级] 学习小组
算法·动态规划·gesp·信息学奥赛
6Hzlia21 小时前
【Hot 100 刷题计划】 LeetCode 72. 编辑距离 | C++ 经典 DP 增删改状态转移
c++·算法·leetcode
穿条秋裤到处跑21 小时前
每日一道leetcode(2026.04.16):距离最小相等元素查询
算法·leetcode·职场和发展