链表题总结

60 阅读1分钟

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

终止条件:当前指针cur及cur.next为空;

public ListNode deleteDuplicates(ListNode head) {
        ListNode cur = head;
        while(cur!=null && cur.next!=null){
            if(cur.val == cur.next.val){ 
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        return head;
    }

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

思路:一边遍历、一边统计相邻节点的值是否相等,如果值相等就继续后移找到值不等的位置,然后删除值相等的这个区间

链表的头节点可能会被删除,要用dummy节点

 public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return head;
        }
        ListNode dummy = new ListNode(0, head);
        ListNode cur = dummy;
        while (cur.next != null && cur.next.next != null) {
            if (cur.next.val == cur.next.next.val) {
                int x = cur.next.val;
                while (cur.next != null && cur.next.val == x){
                    cur.next = cur.next.next;
                }
            } else {
                cur = cur.next;
            }
        }
        return dummy.next;
}

合并两个有序链表

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode newList = new ListNode(0);
        ListNode preHead = newList;
        while(list1 != null && list2 != null ){
            if(list1.val <= list2.val){
                newList.next = list1;
                list1 = list1.next;
            }else{
                newList.next = list2;
                list2 = list2.next;
            }
            newList = newList.next;
        }

        newList.next =list1 == null ? list2 : list1;

        return preHead.next;
    }
   

合并K个有序链表

时间复杂度分析:假设总共有N个节点,每次从队列中取出最小节点的时间复杂度是O(logN),而每个节点最多被取出和插入一次。因此,总的时间复杂度是O(NlogN)。在空间复杂度方面,我们使用了一个PriorityQueue来保存所有链表的头节点,所以空间复杂度是O(N)。

public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        // 创建一个优先队列,指定排序按节点val升序
        PriorityQueue<ListNode> queue = new PriorityQueue<>(
            Comparator.comparingInt(node -> node.val));
        // 将所有链表的头节点加入PriorityQueue
        for (ListNode head : lists) {
            if(head != null)
                queue.offer(head);
        }
        // 创建一个dummy节点作为合并后链表的头节点,一个cur指针来追踪当前合并后链表的末尾节点。
        ListNode cur = new ListNode(0);
        ListNode dummy = cur;
        // 不断从PriorityQueue中取出最小节点,并将其后续节点加入PriorityQueue
        while (!queue.isEmpty()) {
            ListNode minNode = queue.poll();
            cur.next = minNode;
            cur = cur.next;
            if (minNode.next != null) {
                queue.offer(minNode.next);
            }
        }
        return dummy.next;
    }