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

题目描述

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1:

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

示例 2:

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

完整代码参考:GitHub 代码

题解

此题难度定级为简单,主要考察链表的基本操作。

解法1: 去重

思路:通过额外的 list 记录所有不重复的节点(不能使用 set,无序的存储会打乱链表的结构),将 list 中的节点加入到新的链表中。
算法:遍历所有结点并在 list 中存储每个结点的引用(或内存地址)。通过第一个节点构造首节点,然后在首节点之后添加新的  list 中的节点数据。

    public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return null;
        }

        // 构建 list 顺序存储节点值
        List<Integer> list = new ArrayList<>();
        while (head != null) {
            if (!list.contains(head.data)){
                list.add(head.data);
            }
            head = head.next;
        }

        // 构造首节点
        ListNode result = new ListNode(list.get(0));
        for (int i = 1; i < list.size(); i++) {
            // 添加节点
            addListNodeFromLast(result, list.get(i));
        }
        return result;
    }

    public ListNode addListNodeFromLast(ListNode result, int num) {
        ListNode newNode = new ListNode(num);
        // 遍历需要一个额外的存储空间存储当前节点,找到尾节点
        ListNode temp = result;
        // 头节点非空,遍历节点
        while (temp.next != null) {
            // 节点后移
            temp = temp.next;
        }
        // 把当前节点设置为尾节点
        temp.next = newNode;
        return result;
    }

解法2:递归

思路:此题是递归思想解题的一个非常好的应用。由于需要去重操作,所以

算法:递归的三要素。首先明确递归出口,此题中当移动后的头结点为空,或其下一个节点为空时,即可返回,作为递归的出口。其次,以 head.next 作为递归的返回值,为什么要以 head.next 作为返回值而不是 head 呢?这是由于需要把 head 与 head.next 作为比较,如果相同,则需要删除一个节点(即去重)。递归的具体操作就是去除重复节点,即 head = head.next,直接将 head 的下一个节点作为 head 节点,此时删除了 head 节点,完成去重。

具体示例如下:

链表:-3 -> -1 -> 0 -> 0 -> 0 -> 3 -> 3
1. 递归出口返回 head 指向最后一个节点,即 3 -> null
2. 返回值 head.next = 3 -> null,此时 head -> 3 -> 3 -> null
3. 由于 head.data == head.next.data,故此时需要去重,将 head.next 指针指向 head 节点,此时去除第一个 3 节点,完成后 head -> 3 -> null
4. 递归返回下一个值 head = 0 -> 3 -> null,此时 head.data != head.next.data,进入下一次递归
5. 递归返回下一个值 head = 0 -> 0 -> 3 -> null,此时需要去重,将 head.next 指针指向 head 节点,此时去除第一个 0 节点,完成后 head -> 0 -> 3 -> null
6. 以此类推,最终完成去重

    public ListNode deleteDuplicates(ListNode head) {
        // 递归出口
        if (head == null || head.next == null) {
            return head;
        }
        // 返回值
        head.next = deleteDuplicates(head.next);
        // 相邻节点值相同时,删除后面的节点
        if(head.data == head.next.data) {
            head = head.next;
        }
        return head;
    }
©️2020 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值