82. 删除排序链表中的重复元素 II + 链表 + 判重

82. 删除排序链表中的重复元素 II

LeetCode_82

题目描述

题解分析

解法一:复杂解法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode pre = null;
        ListNode current = head;
        while(current != null){
            int val = current.val;
            ListNode cur = current;
            current = current.next;
            int num = 0;
            while(current != null && current.val == val){//遍历所有的重复元素
                num++;
                current = current.next;
            } 
            if(num == 0){//没有重复的元素
                pre = cur;
            }else{//有重复的元素
                if(pre == null){//重复元素是头结点
                    head = current;
                }else{//重复元素不在头结点
                    pre.next = current;
                }
            } 
        }
        return head;
    }
}

解法二:迭代法-边遍历边去重

  1. 解法一太过复杂,需要修改head节点以及使用额外的计数器来判断是否存在重复元素。
  2. 为了解决解法一中需要时刻考虑head节点的问题,我们可以通过设置一个虚拟绩点dumyNode来帮助更快地获取头结点,需要注意的是需要将虚拟节点的next指针指向head节点。
  3. 此外,为了不使用额外的计数器判重,我们可以设置一个pre指针来记录【当前节点之前的最后一个未重复节点】。在跌打的过程中,我们通过修改pre以及pre的next指针可以达到去重的目的。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dumyNode = new ListNode(-1);
        dumyNode.next = head;
        ListNode pre = dumyNode;
        ListNode now = head;
        while(now != null){
            while(now.next != null && now.val == now.next.val){
                now = now.next;
            }
            if(pre.next == now){// 没有重复元素
                pre = now;
            }else{// 存在重复元素
                pre.next = now.next;// 此时pre指针不同,只是修改pre的next指针
            }
            now = now.next;
        }
        return dumyNode.next;
    }
}

解法三:递归法

  1. 与其他大部分链表题目类似,本题可以使用递归的方法来解决,我们可以这样理解deleteDuplicates方法,其删除以head开始的链表中的重复节点并返回头节点。
  2. 递归的边界是,遇到空节点或者单个节点,此时并不需要删除任何节点。
  3. 递归的过程中,如果遇到了head和下一个节点不重复,此时将head.next指向子递归的头节点,并返回head,表明头结点并没有因此改变。如果head节点重复了,那直接返回下一个不重复的节点为参数的子递归头结点。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        if(head.val != head.next.val){
            head.next = deleteDuplicates(head.next);// head.next是否重复还不知道,需要继续递归
        }else{
            ListNode now = head;
            while(now != null && now.val == head.val){
                now = now.next;
            }
            return deleteDuplicates(now);// head此时必然重复了,需要返回新的head
        }
        return head;
    }
}
posted @ 2021-04-01 21:10  Garrett_Wale  阅读(81)  评论(0编辑  收藏  举报