【力扣】82. 删除排序链表中的重复元素 II

存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。

返回同样按升序排列的结果链表。

示例 1:


输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:


输入:head = [1,1,1,2,3]
输出:[2,3]
 

提示:

链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序排列

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

//假设使用额外的空间O(n),使用map记录每个节点的val出现的次数,达到一个统计的目的

public ListNode deleteDuplicates(ListNode head) {

        //使用map key = 具体值,value = 出现的次数
        Map<Integer,Integer> map = new HashMap<>();
        ListNode current = head;

        while(current != null){
            map.put(current.val,map.getOrDefault(current.val,0)+1);
            current = current.next;
        }

        ListNode result = new ListNode();
        current = result;
        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            if(entry.getValue() == 1){
                ListNode temp= new ListNode(entry.getKey());
                current.next = temp;
                current = current.next;
            }
        }
        return result.next;
    }

结果测试用例是跑不通的了,原因很明显:最后使用map遍历,打乱了链表之前的顺序

//那么就不再使用map遍历了,而是使用链表遍历

public ListNode deleteDuplicates(ListNode head) {

        //使用map key = 具体值,value = 出现的次数
        Map<Integer,Integer> map = new HashMap<>();
        ListNode current = head;

        while(current != null){
            map.put(current.val,map.getOrDefault(current.val,0)+1);
            current = current.next;
        }

        ListNode result = new ListNode(0);
        current = result;
        while(head != null){
            if(map.get(head.val) == 1){
                current.next = new ListNode(head.val);
                current = current.next;
            }
            head = head.next;
        }
        return result.next;
    }

这个当然测试用例是ok的,不过同样也存在问题,题目中明显的告诉我们是有序链表,我们这种方式并没有很好地应用到有序链表的特性,所以使用了额外的空间,目前时间复杂度为O(n) 空间复杂度为O(n)

//那就再考虑下怎么不使用额外的空间

其实也比较好想:

public ListNode deleteDuplicates(ListNode head) {

        //这里您就问了,这是什么节点呢?
        //这是一个哑节点,没有存储数字的含义,作用就是:能够指向最终的结果。
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;

        ListNode current = dummyNode;

        while(current.next != null && current.next.next != null){

            //如果说当前节点的下一个跟下一个的下一个值相等,则把下一个下一个都移除
            if(current.next.val == current.next.next.val){

                //看到了吧,把当前值拿出来
                int x = current.next.val;

                //然后在这个循环里,删除current.next的值,如果等于x
                while(current.next != null && current.next.val == x){
                    current.next = current.next.next;
                }
            } else {
                current = current.next;
            }
        }

        return dummyNode.next;

    }

时间复杂度为O(n)、空间复杂度为O(1)

一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻
原文地址:https://www.cnblogs.com/fengtingxin/p/14703847.html