剑指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;
    }
};


相关文章
|
2月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
69 1
|
4月前
|
安全 编译器 C语言
【C++数据结构】string的模拟实现
【C++数据结构】string的模拟实现
|
1月前
|
存储 算法 搜索推荐
链表的中间结点
【10月更文挑战第24天】链表的中间结点是链表操作中的一个重要概念,通过快慢指针法等方法可以高效地找到它。中间结点在数据分割、平衡检测、算法应用等方面都有着重要的意义。在实际编程中,理解和掌握寻找中间结点的方法对于解决链表相关问题具有重要价值。
15 1
|
3月前
链表的中间结点
链表的中间结点
180 57
|
2月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
17 0
|
4月前
|
算法
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点
|
5月前
【数据结构OJ题】链表中倒数第k个结点
牛客题目——链表中倒数第k个结点
39 1
【数据结构OJ题】链表中倒数第k个结点
|
5月前
|
存储 数据格式 运维
开发与运维C++问题之更改数据模型为通用数据结构如何解决
开发与运维C++问题之更改数据模型为通用数据结构如何解决
30 1
|
4月前
【刷题记录】链表的中间结点
【刷题记录】链表的中间结点
|
5月前
【数据结构OJ题】链表的中间结点
力扣题目——链表的中间结点
28 0
【数据结构OJ题】链表的中间结点