题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
题目解析:首先是排序列表,把重复的所有值都删除,而不是保留一个重复值
第一种方法,建立一个新的头结点,就不需要考虑删除头节点和中间节点的区别,直接当做中间节点进行删除
详细代码如下:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead == NULL) return NULL;
ListNode* myFirst = new ListNode(-1);//定义一个自己的头结点,就不用考虑头结点被删除的那种情况了
myFirst->next = pHead;//这个节点指向头指针
ListNode* p = pHead;//定义中间游动的指针
ListNode* pre = myFirst;//定义前指针
while(p != NULL && p->next != NULL){
if(p->val == p->next->val){
int val = p->val;
while(p != NULL && p->val == val){
p = p->next;//找到多个重复值的后第一个不重复值的位置
}
pre->next = p; //前驱指针指向第一个不重复的,进行重复值的删除
}else{
pre = p;
p = p->next;
}
}
return myFirst->next;//自定义指针的下一个才是头指针
}
第二种方法,不需要新建的结点,在删除节点时考虑中间节点和头结点两种情况
//单链表去除重复的数字**不添加头结点的情况,这个方法比较难理解**
ListNode* deleteDuplicationOfHead(ListNode* pHead){
ListNode* pre = NULL;//定义前指针
ListNode* p = pHead;//定义中间游动的指针
ListNode* after = pHead->next;//指向相同值的最后一个
bool flag;
while(p!= NULL)
{
flag = false;
after = p->next;
while(after!= NULL && p->val == after->val)
{
flag = true;
after = after->next;
}
if(flag)
{
if(pre != NULL)//删除不是头结点
{
pre->next = after;
}
else
{
pHead = NULL; //删除头结点
}
}
else
{
if(pre == NULL){pHead = p;}//我感觉删除头结点的方法很难想到
pre = p;
}
p = after;//为什么加上这句话,在while循环中写p->next就会出现段错误,因为p就有可能为空了,空的next肯定就错了
}
return pHead;
}
如果不是排序的数组,那应该怎么删除重复的数值呢,用一个map容器,把数值的值作为map的键值,数值出现的个数作为map的value值,如果出现value值大于1,则将其删除,具体代码如下:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==0) return 0;
map<int,int> m;//把数组值作为key,数组中数值重复的个数做为value
ListNode* p=pHead;
while(p!=0)
{
m[p->val]++; //当key值相同时,value++
p=p->next;
}
//判断head
while(m[pHead->val]>1)
{
pHead = pHead->next;
if(pHead==0) return 0;
}
ListNode* p1=pHead;
ListNode* p2=pHead->next;
while(p2!=0)
{
if(m[p2->val]>1)
{
p2=p2->next;
p1->next=p2;
}
else
{
p2=p2->next;
p1=p1->next;
}
}
return pHead;
}
};
如果不是把所有重复的节点都删了,而是保留把重复的节点删的只剩一个,这样就比较简单了,不用考虑头结点和中间节点的问题了。
具体代码如下所示:
ListNode* deleteDuplicationOfOnly(ListNode* ppHead){
ListNode *p ,*q;
p = ppHead;
q = ppHead->next;
while(q != NULL){
if(p->val == q->val && q != NULL){
p->next = q->next;
q = q->next;
}else{
p = p->next;
q = q->next;
}
}
return ppHead;
}
这个链表指针的问题,思考了好几天,好吧,理解以上方法,也算有了收获。。。。。。。。