牛客网剑指offer第56题——删除链表中重复的节点

题目:

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

思路:

讨论思路之前,先分析题目让我们做什么?删除重复节点,返回头节点。

对此,我将此问题描述成两步:

  • 找到头节点
  • 构成链表
 1 /*
 2 struct ListNode {
 3     int val;
 4     struct ListNode *next;
 5     ListNode(int x) :
 6         val(x), next(NULL) {
 7     }
 8 };
 9 */
10 class Solution {
11 public:
12     ListNode* deleteDuplication(ListNode* pHead)
13     {
14         if(pHead == nullptr)
15             return nullptr;
16         if(pHead->next == nullptr)
17             return pHead;
18         //找到第一个head
19         ListNode*p1=pHead;
20         ListNode*p2=pHead;
21            while(p1 !=nullptr)
22             {
23                if((p1->val == p2->val))//当最坏的情况下,只有一个元素没有重复时,p1->next = null!
24                   p1 = p1->next;
25                 else
26                {
27                    p2 = p1;
28                }
29                 if(p2->next == nullptr || (p2->next !=nullptr && p2->val != p2->next->val))
30                {
31                    pHead = p2;
32                    break;
33                }
34               
35             }
36           
37             if(p1 == nullptr)//说明所有元素都有重复!
38             {
39                 pHead = nullptr;
40                 return pHead;
41             }
42         ListNode*p3 = pHead;
43         p1 = p2->next;//考虑会不会越界
44         while(p1 != nullptr)
45         {
46             if(p1->next!=nullptr && p1->val == p1->next->val)
47             {
48             while(p1->next!=nullptr && p1->val == p1->next->val)
49                   p1 = p1->next;
50             p2->next = p1->next;
51             p1 = p1->next;
52             }
53             else 
54             {
55                 p1 = p1->next;
56                 p2=p2->next;
57                 p3->next = p2;
58             }
59             p3 = p3->next;
60         }
61       return pHead;
62     }
63 };

21行-41行的代码,先帮助我们找到head节点在哪?因为比如链表结构如:1->1->1->2->3->3->4;显然此时head 指向2;而1->1->2;此时head指向2。而1->1->1,此时head指向null;

41行代码之前,完成了什么? 找到head节点,并让p2指向了head。下面就是正式寻找链表的过程。但我们应该注意:此时还需要第三个节点p3。p3的作用是引导构建新的不重复的链表;p1节点是当前访问的链表;p2节点为上一个不重复的节点。

我们先看48-51行代码干了什么?

比如head->2->3->3->3->4->4->5->6;即head指向2。此时p1指向1。显然执行完之后。p2->next指向了4。p1由原来的指向3变为指向4.也就是跳过了重复元素。下一次循环,对于4也是同样的处理。也就是执行完之后,p2-next指向了5,p1指向了5。所以48-51行代码的作用是帮助跳过重复元素。

再看55-57行

最开始p2 = head指向了2,然后呢p2->next指向了5.然后p2更新为p2->next,即p2指向了5。此时将p3->next赋值为p2,则完成了非重复元素的连接过程。然后p3 = p3->next。完成索引+1.

总之:这道题还是有些繁琐的,需要仔细思考细节!

原文地址:https://www.cnblogs.com/shaonianpi/p/12623002.html