目录
- [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. 移除元素-力扣

示例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的值,就把这个值放到新数组中
如图:
最开始src指向的元素等于val,src向后走,des不变
src指向的值不等于val,所以将这个值放到des指向的空间中,接着src和des都向后移
接下来的步骤以此类推,最终会得到一个合适的数组
但是这个方法显然不满足题中要求的原地修改,但是我们可以借助这个思想,只不过是在原数组上进行操作
让src和des都指向原数组,其余步骤都与上面那个方法类似

最开始src指向的元素等于val,src向后走,des不变

接着src指向的元素的值不等于val,把这个值赋给des指向的空间中,接着src des向后挪

src指向的元素的值不等于val,把这个值赋给des指向的空间中,接着src des向后挪

src指向的元素等于val,src向后走,des不变

此时,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. 删除有序数组中的重复项

这道题的思想与上一题思维类似,也是运用双指针遍历法
这道题的做法是:
定义2个指针,一个作为des指向第一个元素,一个作为src指向第二个元素
如果des与src指向的元素相同,就src++
如果des与src指向的元素不同,因为此前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. 合并两个有序数组

合并2个有序数组,这里可以使用归并排序的思想,但是这题与归并思想有些区别
这道题是把值最后都归到数组nums1中,如果还是按照归并做法从前往后操作则会覆盖的值
所以这道题我们从后往前归并

在begin1和begin2中选出较大的值,放到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 序列中删除指定数字

代码如下:
#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]);
}
}






















