顺序表leetcode刷题(C语言版)

本文介绍了两种技术解决方案:利用快慢指针在原数组中移除特定元素,以及使用三指针合并两个有序数组,优化内存操作并保持数组顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.移除元素

3ef8dcd91b6b480dae6b64437441c504.png

对于本题,共有两种解法:

思路一:创建新的数组,遍历原数组,将不为value的值放到新数组中,但本题不允许使用新的数组,因此该方法不行

思路二:使用快慢指针,原数组基础上进行修改,源数据、目标数据,分别用src和dst两个指针指向;src指向的值为value,则往后走,即++;若src指向的值不是value,则nums[dst]=nums[src],dst++,src++

注:value是我所需要删除的值

091c697a948d42e8ad1210c4c81adfd3.jpg

 上图是初始化情况,创建两个变量,让他们指向数组的首地址;先判断src所指向元素是否为value(此处假设value为2),因为不是所以src++

835a3fbddd90414c8d947d070ae8acf3.jpg

 src在++以后,因为指向了value,所以应该将dst指向的数组元素覆盖,换成src当前指向的value元素;在覆盖好以后,dst需要++,同时src也需要++

d6076537810e4f29bab8dc74d48a9230.jpg

 由上图可知,src遍历完整个数组就是循环终止的条件;同时循环结束以后,dst的值恰好是value值的数量,直接返回value

记忆方法:快慢指针各创一,没碰value快++,碰到value一起加

int removeElement(int* nums, int numsSize, int val) {
    int src = 0, dst = 0;
    while (src < numsSize) {
        if (nums[src] == val) {
            src++;
        } else {
            nums[dst] = nums[src];
            dst++;
            src++;
        }
    }
    return dst;
}

上述代码解释:

先创建了两个变量,分别赋值为0(因为数组下标从0开始);while语句的结束条件是src越界,while语句里两种情况,一种是碰到value,一种没碰到(上文已经讲解过);最后返回dst,即value值个数

89b1a2efc7804025881b4986ce541a40.png

 

 

二.合并两个有序数组

7b2c708fac134ec6a88f83b22fba06ee.png 

对于本题,共有两种思路:

思路一:将nums2中数组依次放入到num1数组的后面,用排序算法对nums1进行排序(效率低下)

思路二:三指针,从后往前比较,比谁大,谁大谁往后放,l1和l2比较,谁大谁往l3放,放完的那个向前移动一位,l3也向前移动一位;并且如果L1先出循环,nums2中剩余数据应该存放到nums1中

2fa6cfeca67242ac9d21f19797ac9945.jpg

 创建三个变量,一个指向nums1数组的末端,一个指向nums1元素的末端,一个指向nums2数组的末端;如上图,l2>l1,因此l3所指向的位置存放6,存放完以后l3向前移动一位,l2向前移动一位,l1不动,以此类推

28887b6f163d4289b3f2b60d785066bc.jpg

 在l2走出数组以后,nums1数组已经完成了合并与排序工作;通过上图我们也不难发现,l1如果没有走出数组,但l2走出了数组,这种情况下已经完成了操作;这是因为l1中小的元素要比l2最小的首地址元素还要小,且l1作为有序数组,小的元素已经排好序了,因此不需要动

0833d3705bab4a28aaec45bad39273ec.jpg

 对于这种情况,l1>l2,因此l3指向的内容存放6;存放完l1往前移动一位,l3往前移动一位,l2不动,以此类推

a75c4453696c4350a54d6efce27d9622.jpg

 可是这种情况,在l1走出循环以后,nums2数组里依旧有一个数字1并未存放到nums1数组中;这时就需要循环语句讲nums2中的剩余元素合并到nums1数组中,请注意l2和l1一起减一的关系不变

记忆方法:两个指最后,一个指当中;最后当中比大小,谁大谁放最后;大的指向要--,存放位置也--;若没存放完,循环语句放进去,--关系不能变

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int l1 = m - 1;     // nums1[]已经存放好的元素
    int l3 = m + n - 1; // nums1[]的总长度
    int l2 = n - 1;     // nums2[]存放的元素

    while (l1 >= 0 && l2 >= 0) {
        if (nums1[l1] < nums2[l2]) {
            nums1[l3--] = nums2[l2--];
        } else {
            nums1[l3--] = nums1[l1--];
        }
    }
    while (l2 >= 0) {
        nums1[l3--] = nums2[l2--];
    }
}

 上述代码解释:

创建三个变量,分别指向三个位置;while语句,分l1>l2和l1<l2两种情况;--是后置--,先使用后--;循环结束以后如果nums2里还有数据没存放,循环语句放进去

47b58e4cab8340c8a16bf85094e7ad3f.png 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值