一、题目描述与要求
删除链表中重复的结点_牛客题霸_牛客网 (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},对应的输入输出链表如下图所示:
示例
示例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即可。
思路②【将相邻的两个结点依次进行比较】 时间O(n) 空间O(1)
还是需要定义一个空的头结点,然后从第一个结点开始遍历链表,将两个相邻的结点依次进行比较,如果两个结点的值相等,则获取重复的值,并且把后面所有重复的结点都删除直至没有重复,直至遍历完整个链表,最后返回L->next。
三、具体代码
思路①
#include <unordered_map>
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if(pHead==nullptr) return nullptr; //空链表返回空指针
unordered_map<int, int> 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 <unordered_map>
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;
}
};