题目:
在一个排序的链表中,存在重复的节点,请删除该链表中重复的节点,重复的节点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。
解题思路:
三指针法:
- 删除重复节点,只需要记录当前节点之前的最晚访问过的不重复节点pPre、当前节点pCur、指向当前节点之后节点pNext的三个指针即可;
- 如果当前节点和它后面的几个节点数值相同,那么这些节点都要被剔除,然后更新pPre和pCur;如果不相同,则直接更新pPre和pCur;
- 需要考虑的是,如果第一个节点是重复节点我们该怎么办?这里我们分别处理一下就好,如果第一个节点是重复节点,那么就把头指针pHead也更新一下。
2.代码:
class Solution{
public:
ListNode* deleteDuplication(ListNode* pHead){
//判断 pHead是否指向为空,pHead指向链表第一个元素
if(pHead == NULL) return NULL;
ListNode* pPre = NULL; //指向当前节点之前最晚访问过的不重复节点
ListNode* pCur = pHead; //指向当前处理的节点
ListNode* pNext = NULL; //指向当前节点之后的节点
//循环判断条件是 pCur指针指向是否为空
while(pCur != NULL){
//如果下个节点不为空 且当前节点与下个节点值相同
if(pCur->next != NULL && pCur->next->val == pCur->val){
pNext = pCur->next;
//pNext 继续向后移动,直到当前节点与下一个节点值不相同为止
while(pNext->next != NULL && pNext->next->val == pCur->val){
pNext = pNext->next;
}
//删除阶段
//如果pCur指向链表中的第一个元素,pCur -> ... -> pNext ->...
//要删除pCur到pNext(包含两者), 将指向链表第一个元素的指针pHead指向pNext->next
if(pCur == pHead) pHead = pNext->next;
//如果pCur不指向链表中第一个元素,pPre -> pCur ->...->pNext ->...
//要删除pCur到pNext,即pPre->next = pNext->next
else pPre->next = pNext->next;
//删除后pCur重新调整
pCur = pNext->next;
}
//如果当前节点值与下一个节点值不相同,整体移位
else{
pPre = pCur;
pCur = pCur->next;
}
}
return pHead;
}
};
简洁版:
class Solution{
public:
ListNode* deleteDuplication(ListNode* pHead){
//判断 pHead是否为空
if(!pHead) return NULL;
//设定第一个节点值为参照值(不变)
int val = pHead->val;
//判断下一个节点是否为空
if(pHead->next){
//如果下一个节点与参照值相同
if(pHead->next->val == val){
//向后移动pHead,直到节点值与val不相同为止
//这里的val指的是第一个pHead->val(前提:节点重复的话会在连在一起)
//如果重复节点不在一起,如何处理??
while(pHead && pHead->val == val) pHead = pHead->next;
return deleteDuplication(pHead);
}
//下一个节点与当前节点值不相同时
else{
pHead->next = deleteDuplication(pHead->next);
return pHead;
}
}
else return pHead;
}
};