面试题18-2:删除链表中重复的节点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

FRESH...

正确方法:

  1. 若链表为空或链表只有一个节点,可直接返回链表头结点

    if (pHead == nullptr || pHead->next == nullptr)
             return pHead;
  2. 该链表无头结点或头指针,若首结点就是重复的节点,首结点会被删除,就有问题了,所以应该添加上头指针,指向首结点。
    //创建头指针

     ListNode* head=new ListNode(-1);
     head->next = pHead;

    最后为了防止首结点已删除,返回时应返回头指针下一个节点。
    return head->next;

  3. 在遍历过程中遇到重复的需要删除节点,用prep保存前半部分的链表,用p保存后半部分的链表。

    ListNode* deleteNode=p;
                     p = p->next;
                     delete deleteNode;
                     deleteNode=nullptr;

    代码为:

    ListNode* deleteDuplication(ListNode* pHead)
     {
         if (pHead == nullptr || pHead->next == nullptr)
             return pHead;
         //创建头指针
         ListNode* head=new ListNode(-1);
         head->next = pHead;
    
         ListNode* p = pHead, * prep = head;
         while (p!=nullptr)
         {
             if (p != nullptr && p->next != nullptr && p->val == p->next->val)
             {
                 int duplicateVal=p->val;
                 while (p != nullptr && p->val == duplicateVal)
                 {
                     ListNode* deleteNode=p;
                     p = p->next;
                     delete deleteNode;
                     deleteNode=nullptr;
                 }
                 prep->next = p;
             }
             else
             {
                 prep = p;
                 p = p->next;
             }
         }
         return head->next;
     }

    LONG LONG AGO...

    方法1:

    设置三个指针,p为工作指针,prep为p的前驱,q为p的后继,用于寻找最后一个重复的节点。从头遍历整个链表,若当前节点p与下一个节点的值相同,那么它们就是重复的节点,用指针q继续遍历后面有没有更多相同的重复节点直至到最后一个重复节点,删除p--q这一段节点,继续如此;但要注意的是,若头结点重复需另外处理,得重新设置pHead指针。

    class Solution {
    public:
     ListNode* deleteDuplication(ListNode* pHead)
     {
         if (pHead == nullptr)
             return nullptr;
         //定义三个指针p是工作指针,prep是p的前驱,q是p的后继,p--q范围内的为相同的即将被删除的节点
         ListNode *p = pHead, *prep = nullptr,*q=nullptr;
         while (p!=nullptr)
         {
             q = p->next;
             //若p,q内容相同,则判断q后面是否仍有一样内容的节点,若有,q后移一直到最后的一个相同节点处
             if (q != nullptr && p != nullptr && p->val == q->val)
             {
                 while (q!=nullptr&&q->next!=nullptr&&q->next->val == p->val)
                 {
                     q = q->next;
                 }
                 //若是头结点重复,则重置头结点
                 if (p == pHead)
                 {
                     pHead = q->next;
                     p = pHead;
                 }
                 //若非头结点,则删除p---q段节点即可
                 else
                 {
                     p = q->next;
                     prep->next = p;
                 }
             }
    
             else
             {
                 prep = p;
                 p = p->next;
             }
         }
         return pHead;
     }
    };

    方法2:手动添加一个头结点,指向首元节点。如此就不用了对头结点进行特殊处理了。其他思路同上
    代码:

    ListNode* deleteDuplication(ListNode* pHead)
     {
         if (pHead == nullptr)
             return nullptr;
         //创建头结点
         ListNode* head = new ListNode(0);
         head->next = pHead;
         ListNode *p = head->next, *q = nullptr, *prep = head;
         while (p != nullptr)
         {
             q = p->next;
             //若p与后继指针q所指相同,则继续向后寻找是否有更多重复的节点
             if (p!= nullptr && q != nullptr && p->val == q->val)
             {
                 while (q->next != nullptr && q != nullptr && q->next->val == p->val)
                 {
                     q = q->next;
                 }
                 p = q->next;
                 prep->next = p;
             }
             else
             {
                 prep = p;
                 p = p->next;
             }
         }
         return head->next;
     }
    
全部评论

相关推荐

不愿透露姓名的神秘牛友
11-27 10:48
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务