> 文章列表 > 27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

目录

  • [27. 移除元素-力扣](https://leetcode.cn/problems/remove-element/description/?languageTags=c)
  • [26. 删除有序数组中的重复项](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/)
  • [88. 合并两个有序数组](https://leetcode.cn/problems/merge-sorted-array/)

下面的几道题,都运用一个双指针(下标)遍历法

27. 移除元素-力扣

27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
示例1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]

示例2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]

这道题最容易想到的思想是开辟一个新数组,然后遍历原数组,如果原数组中的某个值不等于val的值,就把这个值放到新数组中

如图:
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
最开始src指向的元素等于valsrc向后走,des不变
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
src指向的值不等于val,所以将这个值放到des指向的空间中,接着srcdes都向后移
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
接下来的步骤以此类推,最终会得到一个合适的数组

但是这个方法显然不满足题中要求的原地修改,但是我们可以借助这个思想,只不过是在原数组上进行操作

srcdes都指向原数组,其余步骤都与上面那个方法类似
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

最开始src指向的元素等于valsrc向后走,des不变
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
接着src指向的元素的值不等于val,把这个值赋给des指向的空间中,接着src des向后挪
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
src指向的元素的值不等于val,把这个值赋给des指向的空间中,接着src des向后挪
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

src指向的元素等于valsrc向后走,des不变
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
此时,src已经遍历出了数组,遍历结束,可以看到实际上操作后的数组就是[2,2],长度是2,也正好是作为下标的des的值,所以最后返回des的值。

代码如下:

int removeElement(int* nums, int numsSize, int val) {int des = 0;for (int src = 0; src < numsSize; src++) {if (nums[src] != val) {nums[des] = nums[src];des++;}}return des;
}

26. 删除有序数组中的重复项

27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
这道题的思想与上一题思维类似,也是运用双指针遍历法

这道题的做法是:
定义2个指针,一个作为des指向第一个元素,一个作为src指向第二个元素
如果dessrc指向的元素相同,就src++
如果dessrc指向的元素不同,因为此前des已经保存了之前的值,所以先des++,再把src的值放到des中,再src++

代码如下:

int removeDuplicates(int* nums, int numsSize){int src = 1;int des = 0;while(src<numsSize){if(nums[src]==nums[des]){src++;}else{nums[++des] = nums[src++];}}return des+1;}

88. 合并两个有序数组

27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
合并2个有序数组,这里可以使用归并排序的思想,但是这题与归并思想有些区别

这道题是把值最后都归到数组nums1中,如果还是按照归并做法从前往后操作则会覆盖的值
所以这道题我们从后往前归并
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)
begin1begin2中选出较大的值,放到des中,然后des--,以及对应元素较大的那个begin减1

接着还有个问题:

  • 如果begin2先循环完,因为数组都是有序的,所以这是已经合并结束
  • 如果begin1先循环完,nums2中的部分数据可能还没有合并到nums1中,所以这里可以把nums2中的元素拷贝到nums1中,拷贝的个数其实是des+1

代码如下:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){int des = nums1Size-1;int begin1 = m-1;int begin2 = n-1;while(begin1>=0&&begin2>=0){if(nums1[begin1]>nums2[begin2]){nums1[des] = nums1[begin1];begin1--;des--;}else if(nums1[begin1]<=nums2[begin2]){nums1[des] = nums2[begin2];begin2--;des--;}}if(begin2<0){return;}else if(begin1<0){memmove(nums1,nums2,sizeof(int)*(des+1));}}

下面还有一个牛客网的题,也是运用双指针(下标)遍历法
牛客网:BC98 序列中删除指定数字
27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

代码如下:

#include <stdio.h>
int main()
{//输入各个值int N= 0;scanf("%d",&N);int arr[N];for(int i=0;i<N;i++){scanf("%d",&arr[i]);}int val = 0;scanf("%d",&val);//删除指定数字int des = 0;for(int src=0;src<N;src++){if(arr[src]!=val){arr[des] = arr[src];des++;}}//输出修改后的序列for(int i = 0;i<des;i++){printf("%d ",arr[i]);}
}