力扣第82题 删除排序链表中的重复元素II

一、题目

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

示例 1:
 

file


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

示例 2:
 

file


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

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

二、思路

  1. 首先别读错题目,题目要求删除所有重复的数字,而不是只保留一位重复数字
    (1->1->2) 要删成(2)
  2. 创建一个虚拟头节点,前面帖子已经有过涉及,虚拟头节点是一种很重要的技巧
  3. 让两个指针p、q去遍历,从虚拟头节点开始,q初始化为p的后一位,循环判断q与q的下一位val值是否相同,如果相同就让q继续向后走一位,再重复该步骤,直到q的下一位不等于q,就让p->next指向q->next,也即实现了删除效果

三、代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* deleteDuplicates(struct ListNode* head){
    struct ListNode *dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy->next = head;

    struct ListNode *p = dummy;
    struct ListNode *q = p->next;

    while(p->next && q->next){
        if(q->val == q->next->val){ 
            //当前位置的后两个结点相同: 因为要删除相同的所有节点,所以有必要在待删除的前一个节点处停留,
            //  故判断当前节点的后两个结点,这样就方便删除了。
            // 此时q就是相同结点的第一个
            while(q->next && q->val == q->next->val){ 
                //从第二个结点开始一直找到最后一个相同的节点的位置 最终q停留在这里
                q = q->next;
            }
            p->next = q->next; //p在这一串相同节点的前一位置,q在这一串相同节点的最后一个节点上,这句代码实现了删除效果
            q = p->next; //q再次指向p的下一位,回到初始状态,进行下一轮便利。
        }
        else {
            //如果当前节点的后两个结点不相同,直接p和q各向前走一位
            p = p->next;

            /**
            // 如果if中写的p->next->val 则不需要这句代码
            因为误打正着,pq会跑到同一位置去,但是q不会执行while, || q执行了while会怎么样?
            并且pq在同一位置,所以p->next = q->next形同摆设,
            相当于只执行了q = p->next,同样实现了q到了p后面的情况。
            这样会造成一些无关代码的运行 对运行速度有一些影响
            */
            q = p->next; 
        }
    }

    return dummy->next;
}

file

四、代码优化

  1. 稍做优化 没有很大影响
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* deleteDuplicates(struct ListNode* head){
    struct ListNode *p = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode *ans = p;

    p->next = head;
    struct ListNode *q = p->next;

    while(p->next && q->next){
        if(q->val == q->next->val){ 
            while(q->next && q->val == q->next->val){ 
                q = q->next;
            }
            p->next = q->next; 
            q = p->next; 
        }
        else {
            p = p->next;
            q = p->next; 
        }
    }

    return ans->next;
}

file

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值