zoukankan      html  css  js  c++  java
  • 【LeetCode-链表】删除排序链表中的重复元素 II

    题目描述

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

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

    题目链接https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/
    做这题之前,可以先做删除排序链表中的重复元素题解.

    思路1

    使用快慢指针来做,首先创建一个 dummyHead 指向原来的链表头,因为链表头可能是重复的,需要删掉。两个指针 fast 和 slow 开始时指向链表头 head,使用指针 pre 指向上一段已经处理好的链表尾(已经处理好就是没有重复节点),然后 fast 先移动,移动到 fast->next->val != slow->val 为止,注意这里要是 fast 的下一个节点的值和 slow 不同,也就是 fast 是重复链表段的最后一个节点。然后分两种情况讨论:

    • 当前节点和下面的节点不重复,也就是 slow==fast,这时候将 pre 设为 fast,将 slow 和 fast 都设置 fast->next 即可;
    • 如果 slow!=fast 说明有重复节点,而且 fast 是重复节点的最后一个节点,所以将 pre->next = fast->next 就可以将重复节点全部删掉,然后 slow 和 fast 均更新为 fast->next;

    下图是存在重复节点时的删除情况

    下图是不存在重复节点时指针的移动的情况

    代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* deleteDuplicates(ListNode* head) {
            if(head==nullptr) return head;
    
            ListNode* dummy = new ListNode(0);
            dummy->next = head;
            ListNode* slow = dummy->next;
            ListNode* fast = dummy->next;
            ListNode* pre = dummy;
            while(fast!=nullptr){
                while(fast!=nullptr && fast->next!=nullptr && fast->next->val==slow->val){
                    fast = fast->next;
                }
    
                if(fast==slow){
                    pre = fast;
                    slow = fast->next;
                    fast = slow;
                }else{
                    pre->next = fast->next;
                    slow = fast->next;
                    fast = fast->next;
                }
            }
            return dummy->next;
        }
    };
    

    思路2

    这题是《剑指Offer》上的一道题,思路 2 也就是《剑指Offer》上的解法。

    我们需要保存3个指针:当前结点curNode、当前结点的前一个结点preNode、当前结点的下一个结点nextNode。由于链表中可能全部是重复的元素,这样的话删除后链表为空,所以需要构造一个新的头结点newHead指向原来的头结点head。首先将newHead赋给preNode, head赋给curNode, head->next赋给nextNode,然后判断curNode->val与nextNode->val是否相等,如果相等的话说明找到了重复元素,这时将nextNode移动到与curNode->val不同的第一个结点,然后更新指针;如果curNode和nextNode的val不同,则更新指针。注意,两种情况下(是否有重复元素)指针的更新方式不同,具体见代码:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* deleteDuplicates(ListNode* head) {
            if(head==nullptr){
                return nullptr;
            }
    
            ListNode* newHead = new ListNode(0);
            newHead->next = head;
            ListNode* preNode = newHead;
            ListNode* curNode = head;
            ListNode* nextNode = curNode->next;
            while(nextNode!=nullptr){
                bool findRepeat = false;    // 是否找到重复节点
                while(curNode!=nullptr && nextNode!=nullptr && curNode->val==nextNode->val){
                    nextNode = nextNode->next;
                    flag = true;
                }
                if(findRepeat){ //找到重复节点
                    curNode = nextNode; 
                    preNode->next = curNode;
                }else{  // 没找到重复节点
                    preNode = curNode;
                    curNode = nextNode;
                }
                if(nextNode!=nullptr){  // 更新nextNode
                    nextNode=nextNode->next;
                }
            }
            return newHead->next;
        }
    };
    
  • 相关阅读:
    Java 实例
    为什么很多程序员工作时都戴耳机?
    HTTP状态码大全
    Eclipse怎么切换工作空间
    maven POM.xml内的标签大全详解
    利用html5的FormData对象实现多图上传
    后台定时器注解方式
    js多定时器
    解决ios上微信无法捕获返回键按钮事件的问题
    上传文件,获取表单数据和文件流
  • 原文地址:https://www.cnblogs.com/flix/p/12670568.html
Copyright © 2011-2022 走看看