C语言力扣刷题7——删除排序链表中的重复元素 II——[快慢双指针法]

力扣刷题7——删除排序链表中的重复元素 II——[快慢双指针法]

一、博客声明

  找工作逃不过刷题,为了更好的督促自己学习以及理解力扣大佬们的解题思路,开辟这个系列来记录。代码可能不是自己写的,不求方法最好,只求更多地理解大佬们的解题思路。


二、题目描述

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

示例 1:
在这里插入图片描述
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]

示例 2:
在这里插入图片描述

输入:head = [1,1,1,2,3]
输出:[2,3]

提示:

链表中节点数目在范围 [0, 300]
-100 <= Node.val <= 100
题目数据保证链表已经按 升序 排列


三、解题思路

1、思路说明

  这题使用了快慢指针双指针去做,具体可以看下面这张图片,fast指针跑的快,slow跑的慢,beforeSlowslow的上一个节点。通过判断nums[fast]nums[slow]是否相同,期间需要定义一个标志位flag来记录当两者不同的时候,中间是否存在相同的数,如下面遍历到第二个阶段nums[slow] = 3, nums[fast] = 4中间就存在3是重复数,因此要执行删除的操作。beforeSlow存在的意义就是防止链表是重复数结尾,如果是重复数结尾,那slow就停止了重复的第一个数上,这个数字也是要删除了,为了不重新遍历一遍,就直接让beforeSlowslow的上一个节点,直接让beforeSlow->next = NULL
在这里插入图片描述

 


四、解题代码(附注释)

struct ListNode* deleteDuplicates(struct ListNode* head) {
    if(head == NULL || head->next == NULL){ //如果链表节点长度小于等于1,直接返回head;
        return head;
    }
    struct ListNode* preHead = malloc(sizeof(struct ListNode));//建立一个检查头
    preHead->val = 0;
    preHead->next = head;
    struct ListNode* slow = preHead->next;//定义慢指针
    struct ListNode* fast = preHead->next->next;//定义快指针
    struct ListNode* beforeSlow = preHead;//定义慢指针的前一个节点
    int flag = 0;//一个标志位,用于标记快慢指针是否正在重复
    while(fast){
        if(fast->val == slow->val){
            flag = 1; //快慢指针经历重复数,标志位置1
            fast = fast->next; // 快指针移动
            if(fast == NULL){  // 如果到了节点末尾,说明是重复数结尾,
                beforeSlow->next = NULL;//因此慢指针的前一个节点的next需要指向NULL,然后break
                break;
            }
            continue;
        } else {
            if(flag == 0){ //标志位为0,说明不是经历重复数后判断的不同,因此慢指针移动
                slow = slow->next;
                beforeSlow = beforeSlow->next;
            } else {// 否则 slow = fast , 将标志位置0
                slow->val = fast->val;
                slow->next = fast->next;
                flag = 0;
            }
        }

        fast = fast->next;// 快指针移动
    }
    struct ListNode* result = preHead->next;
    free(preHead);
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值