开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
题目
描述
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。 例如: 给出的链表为1→2→3→3→4→4→5, 返回1→2→5. 给出的链表为1→1→1→2→3, 返回2→3.
数据范围:链表长度 0≤n≤10000,链表中的值满足∣val∣≤1000
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(1),时间复杂度 O(n)
示例1
输入:
{1,2,2}
返回值:
{1}
示例2
输入:
{}
返回值:
{}
分析
分析特殊情况
由题目我们可以知道,当链表为空或者链表只有一个元素时,只需要返回链表头即可。
分析一般情况
首先由于我们不知道是否需要删除头结点,最好新建一个dummy节点指向头结点;
然后我们对链表进行遍历,检查前后两个元素是否相等:
- 如果不等,则往后继续遍历;
- 如果相等,那么我们需要进行内循环,向后找到所有相等的节点,并删除它们。
这里我们采用了三个节点pPrePre初始化为dummy节点,pPre初始化为head,pCur初始化为head->next,然后遍历对比pPre与pCur的值,如果不等,则更新上面三个指针,如果相等,则先删除pCur到最后一个相同值的节点,然后删除pPre,然后建立新的连接,并更新。
最后返回pReturn->next.
代码示例
注意,这里也涉及到我们在删除节点时的操作,需要使用一个临时变量缓存需要删除的节点,还有,我们最开始创建的dummy节点也不要忘记一并删除。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* deleteDuplicates(ListNode* head) {
// write code here
if(nullptr == head || nullptr == head->next){
return head;
}
ListNode *pReturn = new ListNode(-1);
pReturn->next = head;
ListNode *pPrePre = pReturn;
ListNode *pPre = head;
ListNode *pCur = head->next;
while(nullptr != pCur){
if(pPre->val != pCur->val){
pPrePre = pPre;
pPre = pCur;
pCur = pCur->next;
}else{
//delete pCur same value
while(nullptr != pCur && pPre->val == pCur->val){
ListNode* pTemp = pCur;
pCur = pCur->next;
delete pTemp;
pPre->next = pCur;
}
// delete pPre
delete pPre;
pPre = pCur;
pPrePre->next = pPre;
if(nullptr == pCur){
break;
}else{
pCur = pCur->next;
}
}
}
ListNode *pTemp = pReturn;
pReturn = pReturn->next;
delete pTemp;
return pReturn;
}
};