题目描述
描述:编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
输入:[1, 2, 3, 3, 2, 1]
输出:[1, 2, 3]
输入:[1, 1, 1, 1, 2]
输出:[1, 2]
链表长度在[0, 20000]范围内。
链表元素在[0, 20000]范围内。
解题思路
思路1:最直观的想法是,创建一个头结点L,其指向链表的第一个结点head,然后为了删除方便,使用p指向当前结点的前一个结点,其初始化为L,再使用一个uset存储不重复的元素,当当前结点不为空,即p&&p->next,如果能在uset中找到当前结点值,则表示重复,于是删除当前结点,注意,此时只是改变p->next的指向,但是不改变p喔,反之如果不能在uset中找到当前结点值,则表示不重复,故将当前结点值插入uset,并且将p后移一位。
ListNode* removeDuplicateNodes(ListNode* head)
{
// 存储不重复的元素值
unordered_set<int> uset;
// 头结点
ListNode* L=new ListNode(0);
L->next=head;
// 从头节点开始
ListNode* p=L;
// 为了方便 p指向当前节点的前一个节点 要求当前节点不为空
while(p&&p->next!=NULL)
{
// 找到 出现重复
if(uset.find(p->next->val)!=uset.end())
p->next=p->next->next;
// 没找到 插入
else
{
uset.emplace(p->next->val);
p=p->next;
}
}
return L->next;
}
总结:以前我们处理的是在排序后的链表中删除重复元素,由于其重复元素都是连续出现的,所以我们没有使用额外的存储空间来存储非重复值,而是直接判断当前的下一个与当前的下下一个是否相等,如果相等则保存相等值来进行删除。现在我们处理的是在未排序的链表中删除重复元素,故我们需要使用uset来存储非重复值来帮助我们判断。但是,有一个共同点,为了方便删除,我们都会创建一个头结点,以及使用一个指针指向当前节点的前一个节点,即如果出现重复元素,则直接使用前一个节点来进行删除,注意,此时是不需要将前一个节点后移的,只有当前未出现重复才需要后移前一个节点。同时,当判断p->next不为空时,一定要先判断p不为空,否则会报错喔。