1.题目
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
链表结构
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
2.基本想法
就是删除重复的节点。没有什么trick。但是要注意的地方真不少。
设指针头节点为pHead1
易错点:
- 头节点是重复节点和链表中间的节点p是重复节点的处理方法不一样
- 头节点的话,你可以直接删除;p是重复节点,你删除p和p的直接后驱节点,但是你还要保证p的前驱节点的next指针有指向。这就是他们不同的地方
- 一对一对删除节点是错误的,因为一个重复节点里面存储的值可能重复了奇数次
验证实例:
- {1,1}
- {1,1,1,2,2}
- {1,2,2,2,3,3,4}
- {1,2,2,2}
3.代码
代码1
ListNode* deleteDuplication(ListNode* pHead) { if(pHead==NULL || pHead->next==NULL){ return pHead; } ListNode *p,*p1,*p2; while(pHead!=NULL && pHead->next!=NULL && pHead->val==pHead->next->val){ p=pHead->next; while(p!=NULL && p->val==pHead->val){ p1=p->next; pHead->next=p1; delete p; p=p1; } delete pHead; pHead=p; } p=pHead; while(p!=NULL && p->next!=NULL){ if(p->val!=p->next->val){ p=p->next; }else{ p1=p->next; while(p1!=NULL && p1->val==p->val){ p2=p1->next; p->next=p2; delete p1; p1=p2; } if(p1==NULL){ p2=pHead; while(p2->next!=p) p2=p2->next; p2->next=NULL; delete p; break; }else{ swap(p->val,p1->val); p2=p1->next; p->next=p2; delete p1; } } } return pHead; }
代码2
ListNode* deleteDuplication(ListNode* pHead) { // 如果重复的节点不止有两个呢? if(pHead==NULL) return NULL; ListNode *pLow,*pHigh,*pMiddle,*p; // 先选出头节点 pLow=pHead; pHigh=pLow->next; while( pLow!=NULL && pHigh!=NULL && pLow->val==pHigh->val){ while(pHigh!=NULL && pLow->val==pHigh->val ){ p=pLow; pLow=pHigh; pHigh=pHigh->next; delete p; } pHead=pHigh; delete pLow; pLow=pHead; if(pLow!=NULL) pHigh=pLow->next; } pMiddle=pHigh; if(pHigh!=NULL) pHigh=pHigh->next; while( pHigh!=NULL && pMiddle!=NULL ){ if( pHigh->val==pMiddle->val ){ while( pHigh!=NULL && pMiddle!=NULL && pMiddle->val==pHigh->val ){ pLow->next=pMiddle->next; delete pMiddle; pMiddle=pHigh; pHigh=pHigh->next; } pLow->next=pMiddle->next; delete pMiddle; pMiddle=pHigh; if(pHigh!=NULL) pHigh=pHigh->next; }else{ pLow=pMiddle; pMiddle=pHigh; pHigh=pHigh->next; } } return pHead; }
ps:代码2是我第一次遇见这道题时,提交的。有时我就在想,代码到底是越写越好,还是越写越差。经验即束缚,代码1中在删除节点的时候,我为什么不记录一下前一个节点是什么呢?大脑中还是保留着做过如何在 O(1) 时间内删除链表中的节点?这道题后,书本给我的答案或者经历给我的答案。
写代码也时时刻刻能感觉到自己的局限。多么可怕的一件事情呀