83. 删除排序链表中的重复元素 + 链表删除节点

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

LeetCode_83

题目描述

相似题目

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

题解分析

解法一:复杂解法

/**
 * 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 now = head;
        ListNode pre = null;
        while(now != null){
            boolean flag = false;
            if(pre != null){
                if(pre.val == now.val){
                    ListNode temp = now.next;
                    pre.next = temp;
                    now = temp;
                    flag = true;
                }
            }
            if(!flag){
                pre = now;
                now = now.next;
            }
        }
        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.next = now;// 此时pre指针不同,只是修改pre的next指针
            }
            pre = now;
            now = now.next;
        }
        return dumyNode.next;
    }
}

解法三:递归法

  1. 与其他大部分链表题目类似,本题可以使用递归的方法来解决,我们可以这样理解deleteDuplicates方法,其删除以head开始的链表中的重复节点并返回头节点。
  2. 递归的边界是,遇到空节点或者单个节点,此时并不需要删除任何节点。
  3. 递归的过程中,如果遇到了head和下一个节点不重复,此时将head.next指向子递归的头节点,并返回head,表明头结点并没有因此改变。否则,找到重复节点的第一个不同的节点,并将其作为参数进行子递归,并将head的next指针指向自递归头节点。
  4. 最后,统一返回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;
            }
            head.next = deleteDuplicates(now);// head此时必然重复了,需要返回新的head
        }
        return head;
    }
}
posted @ 2021-03-18 10:10  Garrett_Wale  阅读(47)  评论(0编辑  收藏  举报