8.剑指offer-删除链表中重复节点

来源:互联网 发布:安卓软件挂 编辑:程序博客网 时间:2024/06/07 20:44

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)时间内删除链表中的节点?这道题后,书本给我的答案或者经历给我的答案。

    写代码也时时刻刻能感觉到自己的局限。多么可怕的一件事情呀

0 0
原创粉丝点击