力扣83题:删除排序链表中的重复元素

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

提示:

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

【方法一】单指针

第一步:如果头节点和头节点的下一个节点为空,则返回头结点。

第二步:创建一个指针p指向头指针。

第三步:如果头节点和头节点的下一个节点不为空,判断头节点和头节点下一个节点的数据是否相等(由题目可以知道,链表的第一个节点为头节点,且头结点中含有数据),如果相等,将p的后继指针指向p的后继的后继(相当于删除重复的后面那个数据);如果不相等,p指针移动到p的后继(相当于向后遍历)。

第四步:返回最后删除后的链表。

具体案例分析:

head=[1,1,2,3,3]

开始时,p指向第一个节点1(也就是head),判断p的后继和p中的数据是否相等。相等则将p的后继指针指向p的后继的后继(也就是指向2);然后进行下一轮判断,此时p指向1,p的后继指向2,不相等,则p指针移动到p的后继(也就是说现在p指向2);继续进行后面判断.............

C语言具体代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* deleteDuplicates(struct ListNode* head){
     if(head==NULL || head->next==NULL){
        return head;
    }
    struct ListNode* p = head;
    while (p != NULL && p->next != NULL)
        if (p->val == p->next->val){
            p->next = p->next->next;
        } 
        else {
            p = p->next;
        }
    return head;

}

时间复杂度O(n);空间复杂度O(1)

【方法二】双指针

第一步:如果头节点和头节点的下一个节点为空,则返回头结点。

第二步:创建一个指针p指向头指针和一个移动指针q。

第三步:如果头节点和头节点的下一个节点不为空,判断头节点和头节点下一个节点的数据是否相等(由题目可以知道,链表的第一个节点为头节点,且头结点中含有数据),如果相等,将q指针指向p指针的下一个节点,将p的后继指针指向p的后继的后继,然后释放掉q指针free(q)(相当于删掉重复的数据,也就是q指针所指的),如果不相等,p指针移动到p的后继(相当于向后遍历)。

第四步:返回最后删除后的链表。

具体案例分析:

head=[1,1,2,3,3]

开始时,p指向第一个节点1(也就是head),判断p的后继和p中的数据是否相等。如果相等,将q指针指向p的后继(也就是第二个1),然后将p的后继指针指向p的后继的后继,最后释放掉q(也就是删掉第二1)。然后进行下一轮判断,此时p指向1,p的后继指向2,不相等,则p指针移动到p的后继(也就是说现在p指向2);继续进行后面判断.............

C语言具体代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* deleteDuplicates(struct ListNode* head){
     if(head==NULL || head->next==NULL){
        return head;
    }
    struct ListNode *p = head;
    struct ListNode *q ;
    while (p != NULL && p->next != NULL) {
        if (p->next->val == p->val) {
            q = p->next;
            p->next = p->next->next;
            free(q);
        } else {
            p = p->next;
        }        
    }
    return head;

}

时间复杂度O(n);空间复杂度O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值