9.删除链表中的重复结点

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

题目描述

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


/*

struct ListNode {

   int val;

   struct ListNode *next;

   ListNode(int x) :

       val(x), next(NULL) {

   }

};

*/

class Solution {

public:

   ListNode* deleteDuplication(ListNode* pHead)

   {

   }

};

解法:


class Solution {

public:

   ListNode* deleteDuplication(ListNode* pHead)

 {

   if( pHead == NULL ) return pHead;

   //创建3个链表结点变量

   ListNode *pre = NULL; //指向前面最晚访问过的不重复结点

   ListNode *p = pHead; //指向当前处理的结点

   ListNode *q = NULL; //指向当前处理结点后面结点

   // 其中的每个链表结点分别代表了phead的各个结点 以及改变了链表的各个指向

   while( p != NULL )

   {

      //分两种情况:

       //一种是后结点和前结点有重复

       //当前结点p,(其实是p指向当前结点),与它下一个结点p->next的val相同,说明要删掉有这个val的所有结点

       if( p->next != NULL && p->next->val == p->val )

       {

           q = p->next;

           //找到q,它指向最后一个与p val相同的结点,那p 到 q (包含) 都是要删除的

           while( q != NULL && q->next != NULL && q->next->val == p->val )

           {

               q = q->next;

           }

           //如果p指向链表中第一个元素,p -> ... -> q ->... , 要删除p到q, 将指向链表第一个元素的指针pHead指向q->next。

           if( p == pHead )

           {

               pHead = q->next;

           }

           else//如果p不指向链表中第一个元素,pre -> p ->...->q ->... ,要删除p到q,即pre->next = q->next

           {

               pre->next = q->next;

           }

           //当前处理的p要向链表尾部移动

           p = q->next;

       }

       //第二种是后结点和前结点无重复

       else//如果没有重复结点,则一直往后移动

       {

           pre = p;

           p = p->next;

       }

   }

   return pHead;//注意返回的必须是PHead,因为此时的PHead链表已经被改变了指向

}

};

解法2:递归


class Solution {

   public:

    ListNode* deleteDuplication(ListNode* pHead)

    {

       if (pHead == nullptr || pHead->next == nullptr)

       { // 只有0个或1个结点,则返回

           return pHead;

       }

       // 当前结点是重复结点

       if (pHead->val == pHead->next->val)

       {

       

           ListNode* pNode = pHead->next;

           while (pNode != nullptr && pNode->val == pHead->val)

           {

               // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点

               pNode = pNode->next;

           }

           //相当于将不重复的结点放入栈中

           return deleteDuplication(pNode); // 从第一个与当前结点不同的结点(此结点不重复)开始递归;

       }

      // 当前结点不是重复结点

      else

        {

          //相当于将不重复的结点放入栈中

           pHead->next = deleteDuplication(pHead->next); // 保留当前结点,从下一个结点开始递归

           return pHead;

        }

    }

};

目录
相关文章
|
20天前
19 删除链表的倒数第 N 个结点
19 删除链表的倒数第 N 个结点
|
1月前
|
算法
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
|
1月前
|
算法 安全 数据处理
LeetCode刷题---707. 设计链表(双向链表-带头尾双结点)
LeetCode刷题---707. 设计链表(双向链表-带头尾双结点)
|
3月前
牛客网:NC69 链表中倒数最后k个结点
牛客网:NC69 链表中倒数最后k个结点
17 0
|
3月前
|
存储 Go
golang力扣leetcode 19.删除链表的倒数第N个结点
golang力扣leetcode 19.删除链表的倒数第N个结点
31 0
【剑指offer】-链表中倒数第K个结点-14/67
【剑指offer】-链表中倒数第K个结点-14/67
【剑指offer】-链表中倒数第K个结点-14/67
LeetCode | 19. 删除链表的倒数第 N 个结点
LeetCode | 19. 删除链表的倒数第 N 个结点
数据结构|双向链表|带头结点|头插|尾插|尾删|头删
数据结构|双向链表|带头结点|头插|尾插|尾删|头删
|
1月前
LeetCode刷题---876. 链表的中间结点(快慢指针)
LeetCode刷题---876. 链表的中间结点(快慢指针)
|
1月前
|
C语言
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】