剑指offer(C++)-JZ76:删除链表中重复的结点(数据结构-链表)

简介: 剑指offer(C++)-JZ76:删除链表中重复的结点(数据结构-链表)

题目描述:

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5  处理后为 1->2->5


数据范围:链表长度满足 1<=n<=1000 ,链表中的值满足 1<=nval<=1000


进阶:空间复杂度O(n)  ,时间复杂度 O(n)  


例如输入{1,2,3,3,4,4,5}时,对应的输出为{1,2,5},对应的输入输出链表如下图所示:

示例:

输入:

{1,2,3,3,4,4,5}


返回值:

{1,2,5}

解题思路:

本题考察数据结构链表的使用。本题常用两种解法。


  1. set遍历法。第一遍遍历用set存储重复的值,第二遍遍历将重复的值对应的结点删掉。该方法的好处是即使链表未排序,也能使用。
  2. 直接删除法。首先建立哨兵vhead,定义pre和cur前后指针进行遍历;遍历过程中如果出现前后重复的情况,则将cur连接到下一个非重复的结点,并重新将pre与其连接;若前后未重复,则前后指针同步向后进行;一次遍历完成后,重复的结点已删除。该方法适合已经排序的链表。

测试代码:

解法一:set遍历法

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if(!pHead)
            return pHead;
        set<int> s;
        ListNode *pre=pHead;
        ListNode *cur=pHead->next;
        // 第一遍遍历把重复的数值放入set
        while(cur)
        {
            if(pre->val==cur->val)
            {
                s.insert(pre->val);
            }
            pre=pre->next;
            cur=cur->next;
        }
        ListNode *vhead=new ListNode(-1);
        vhead->next=pHead;
        pre=vhead;
        cur=pHead;
        // 第一遍遍历把重复数值对应的结点删除
        while(cur)
        {
            if(s.count(cur->val))
            {
                cur=cur->next;
                pre->next=cur;
            }
            else{
                pre=pre->next;
                cur=cur->next;
            }
        }
        return vhead->next;
    }
};

解法二:直接删除法

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if(!pHead)
            return pHead;
        ListNode *vhead=new ListNode(-1);
        vhead->next=pHead;
        ListNode *pre=vhead;
        ListNode *cur=pHead;
        // 遍历删除重复结点
        while(cur)
        {
            // 如果有重复结点
            if(cur->next && cur->val==cur->next->val)
            {
                cur=cur->next;
                // 若有连续重复的情况,将cur指向最后一次出现重复的结点
                while(cur->next && cur->val==cur->next->val)
                {
                    cur=cur->next;
                }
                // 连接下一个非重复的结点
                cur=cur->next;
                pre->next=cur;
            }
            // 若无重复结点,同步指向下一个
            else{
                pre=pre->next;
                cur=cur->next;
            }
        }
        return vhead->next;
    }
};


相关文章
|
14天前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
44 1
|
3月前
|
安全 编译器 C语言
【C++数据结构】string的模拟实现
【C++数据结构】string的模拟实现
|
2月前
链表的中间结点
链表的中间结点
176 57
|
17天前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
13 0
|
3月前
|
算法
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点
|
4月前
【数据结构OJ题】环形链表
力扣题目——环形链表
36 3
【数据结构OJ题】环形链表
|
4月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
51 1
【数据结构OJ题】复制带随机指针的链表
|
4月前
【数据结构OJ题】环形链表II
力扣题目——环形链表II
28 1
【数据结构OJ题】环形链表II
|
4月前
【数据结构OJ题】相交链表
力扣题目——相交链表
32 1
【数据结构OJ题】相交链表
|
4月前
【数据结构OJ题】链表中倒数第k个结点
牛客题目——链表中倒数第k个结点
32 1
【数据结构OJ题】链表中倒数第k个结点