剑指offer——JZ76 删除链表中重复的结点 解题思路与具体代码【C++】

一、题目描述与要求

删除链表中重复的结点_牛客题霸_牛客网 (nowcoder.com)

题目描述

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

数据范围:链表长度满足 0≤n≤1000  ,链表中的值满足1≤val≤1000 

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

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

剑指offer——JZ76 删除链表中重复的结点 解题思路与具体代码【C++】_第1张图片

示例

示例1:

输入:{1,2,3,3,4,4,5}

返回值:{1,2,5}

示例2:

输入:{1,1,1,8}

返回值:{8}


二、解题思路

思路①【利用无序容器哈希表】时间O(n) 空间O(n)

首先我们需要找到重复结点,因此我们可以利用无序容器unordered_map来统计每个结点出现的次数。统计完之后,我们只需要在遍历每个结点的时候查看其出现的次数是否等于1即可知道它是不是重复结点,是的话直接将结点删去即可。

此时如果我们只利用pHead指针显然是无法实现个别结点的删除,比如第一个结点。因而我们可以添加一个空的头结点在第一个结点前面,并且令p指向它,而后就是对p->next进行判断即可,这样所有结点都会被判断到。最后只需要返回L->next即可。

剑指offer——JZ76 删除链表中重复的结点 解题思路与具体代码【C++】_第2张图片

思路②【将相邻的两个结点依次进行比较】 时间O(n) 空间O(1)

还是需要定义一个空的头结点,然后从第一个结点开始遍历链表,将两个相邻的结点依次进行比较,如果两个结点的值相等,则获取重复的值,并且把后面所有重复的结点都删除直至没有重复,直至遍历完整个链表,最后返回L->next。

剑指offer——JZ76 删除链表中重复的结点 解题思路与具体代码【C++】_第3张图片


三、具体代码

思路①

#include 
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if(pHead==nullptr) return nullptr; //空链表返回空指针
        unordered_map map;//利用哈希表计算每个结点出现的次数
        ListNode*p=pHead;//用于遍历链表
        while(p){
            map[p->val]++;
            p=p->next;
        }
        ListNode* L=new ListNode(0);//添加一个空的头结点 为了从第一个结点开始判断
        L->next=pHead;//将空头结点与第一个结点连接起来
        p=L;//从头开始遍历链表
        while(p->next){ //第一个结点开始
            //只要这个结点出现的次数大于1次 重复的结点会重复进行删除
            if(map[p->next->val]!=1){ 
                p->next=p->next->next; //删去这个结点
            }
            else {
                p=p->next; //否则的话访问下一个结点
            }
        }
        return L->next;
    }
};

思路②

#include 
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if(pHead==nullptr) return nullptr; //空链表返回空指针
        ListNode* L=new ListNode(0);//添加一个空的头结点 为了从第一个结点开始判断
        L->next=pHead;//将空头结点与第一个结点连接起来
        ListNode *p=L;//从头开始遍历链表
        while(p->next&&p->next->next){ //对两个相邻的结点进行判断
            if(p->next->val==p->next->next->val){ //相邻两个结点相等 即为重复结点
                int temp=p->next->val;//获取当前重复结点的值
                while(p->next&&p->next->val==temp){//将相同的结点都删除
                    p->next=p->next->next; //删掉重复结点
                }
            }
            else {
                p=p->next;
            }
        }
        return L->next;
    }
};

你可能感兴趣的:(剑指offer,算法,c++,数据结构,链表)