zoukankan      html  css  js  c++  java
  • Leetcode 82. 删除排序链表中的重复元素 II

    问题描述

    给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。

    示例 1:

    输入: 1->2->3->3->4->4->5
    输出: 1->2->5
    示例 2:

    输入: 1->1->1->2->3
    输出: 2->3

    代码

    法一、采用找重复之前和找重复之后,时间复杂度 O(n2) ----自己所写

     1 class Solution {
     2 public:
     3     ListNode* searchPreDuplicates(ListNode *head, ListNode *p){
     4         ListNode* q = head;
     5         while(q != NULL&& q->next != NULL){
     6             if(q->next == p)
     7                 break;
     8             q = q->next;
     9         }
    10         return q;
    11     }
    12     ListNode* deleteDuplicates(ListNode* head) {
    13         ListNode* preHead= new ListNode(-1);
    14         ListNode *p = preHead;
    15         p->next = head;
    16         p = p->next;
    17         //ListNode* p = head;
    18         while(p != NULL && p->next != NULL){
    19             if(p->val != p->next->val){
    20                 p = p->next;
    21             }
    22             else{
    23                 ListNode* pre = searchPreDuplicates(preHead,p);
    24                 
    25                 while(p != NULL && p->next != NULL && p->val == p->next->val)  p = p->next;  
    26                 //找重复数字的下一个节点
    27                 
    28                 ListNode* post = p->next;
    29                 
    30 
    31                 pre->next = post;
    32                 p = post;
    33 
    34             }
    35         }
    36         return preHead->next;
    37     }
    38 };

    法二、采用快慢指针,时间复杂度O(n)-----学习他人

     1 class Solution {
     2 public:
     3  
     4     ListNode* deleteDuplicates(ListNode* head) {
     5         //创建哑节点
     6         ListNode *preHead = new ListNode(-1);
     7         preHead->next = head;
     8         //创建快慢指针 
     9         ListNode *slow = preHead;  //慢指针用于指向重复数字的前一个数字
    10         ListNode *fast = head;   //快指针用于寻找重复数字
    11 
    12         while(fast != NULL && fast->next != NULL){
    13             if(fast->val != fast->next->val){   //分情况讨论,如1->2和1->1->2
    14                 if(slow->next == fast ) //此时之前没有重复数字
    15                     slow = fast;
    16                 else{
    17                     slow->next = fast->next;   //此时将略过重复数字
    18                 }
    19             } 
    20             fast = fast->next;
    21         }
    22         
    23         if(slow->next != fast) slow->next = fast->next;
    24         
    25         return preHead->next;
    26         
    27     }
    28 };

    此方法不能忽略最后的[1,1]情况判断,即上面第23行很关键。因为快慢指针是前后挨着。若输入的数据全部是重复数字,那么相当于fast指针一直前进,没有执行更新slow指针的值(第17行)

    就跳出循环,所以最后再更新slow指针的值。

    总结

    1.本题重复数字在开头的处理方法为 : 哑节点

    2.学习了对于链表设置快慢指针的方法,此方法的实质依旧是未重复数字之前的数字指向重复完成数字之后,只不过实现时用到了双指针

    class Solution {
    public:
        ListNode* searchPreDuplicates(ListNode *head, ListNode *p){
            ListNode* q = head;
            while(q != NULL&& q->next != NULL){
                if(q->next == p)
                    break;
                q = q->next;
            }
            return q;
        }
        ListNode* deleteDuplicates(ListNode* head) {
            ListNode* preHead= new ListNode(-1);
            ListNode *p = preHead;
            p->next = head;
            p = p->next;
            //ListNode* p = head;
            while(p != NULL && p->next != NULL){
                if(p->val != p->next->val){
                    p = p->next;
                }
                else{
                    ListNode* pre = searchPreDuplicates(preHead,p);
                    
                    while(p != NULL && p->next != NULL && p->val == p->next->val)  p = p->next;  
                    //找重复数字的下一个节点
                    
                    ListNode* post = p->next;
                    

                    pre->next = post;
                    p = post;

                }
            }
            return preHead->next;
        }
    };
  • 相关阅读:
    【转】linux之fsck命令
    【转】linux之mkfs/mke2fs格式化
    【转】linux_fdisk命令详解
    【转】linux之ln命令
    [转]linux的du和df命令
    [转]Linux之type命令
    [转]Linux下which、whereis、locate、find 命令的区别
    [转]Linux的chattr与lsattr命令详解
    get 与post 的接收传值方式
    在asp.net前台页面中引入命名空间 和连接数据库
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/12989894.html
Copyright © 2011-2022 走看看