力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7

文章目录

  • 1. 合并两个有序链表(简单)
  • ==2. 合并 K 个升序链表(困难)==
  • 3. 环形链表(简单)
  • 4. 环形链表 II (中等)
  • 5. 链表的中间结点(简单)
  • 6. 相交链表(简单)
  • 7. 删除链表的倒数第 N 个结点(中等)

1. 合并两个有序链表(简单)

地址: https://leetcode-cn.com/problems/merge-two-sorted-lists/ss
2021/11/23
做题反思:第三次做了,思路清晰很多,但仍有两处问题

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        /**
         *2021/11/23
         *注意此处 dummy 的创建方式
         *错误写法 
         *ListNode dummy = null;
         *ListNode p = dummy;
         */ 
        ListNode dummy = new ListNode(-1), p = dummy;

        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                p.next = l1;
                l1 = l1.next;
            }else {
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }
        /**2021/11/23
         *此处用 if 判断即可, 不是用 while -> 超时
         */
        if (l1 != null) {
            p.next = l1;
        }
        if (l2 != null) {
            p.next = l2;
        }
        return dummy.next;
    }
}

力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第1张图片

2. 合并 K 个升序链表(困难)

地址:https://leetcode-cn.com/problems/merge-k-sorted-lists/submissions/
2021/11/23
做题反思:

  1. 思路能想到优先队列,但是实现过程没想通; -> 思考了10分钟,最终再次看答案学习解法
  2. 第三次:看答案后写出,弄懂并复习了之前有些不清楚及模糊的知识点
    期待下次ac
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0) {
            return null;
        }
        ListNode dummy = new ListNode(-1), p = dummy;
        // 泛型 https://blog.csdn.net/weixin_46644403/article/details/120945530
        // 优先队列 https://labuladong.gitee.io/algo/2/20/50/
        PriorityQueue<ListNode> pq = new PriorityQueue<>(
            // lambda 表达式 https://blog.csdn.net/weixin_46644403/article/details/120688915
            (a,b) -> a.val - b.val
        );
        for (ListNode head : lists) {
            if (head != null) {
                pq.add(head);
            }
        }
        while (!pq.isEmpty()) {
            // poll() https://www.runoob.com/java/data-queue.html
            ListNode node = pq.poll();
            p.next = node;
            if (node.next != null) {
                pq.add(node.next);
            }
            p = p.next;
        }
        return dummy.next;
    }
}

力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第2张图片
复杂度:O(NlogK)

3. 环形链表(简单)

地址:https://leetcode-cn.com/problems/linked-list-cycle/
2021/11/24
ac

public class Solution {
    public boolean hasCycle(ListNode head) {
        /**
         ListNode slow, fast;
         slow = fast = head;
         */
        ListNode slow = head, fast = head;

        while(fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                return true;
            }
        }
        return false;
    }
}

力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第3张图片

4. 环形链表 II (中等)

地址:https://leetcode-cn.com/problems/linked-list-cycle-ii/
2021/11/24
做题反思:无环条件遗漏

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head, fast = head;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                break;
            }
        }
        // 判断无环
        if (fast == null || fast.next == null) {
            return null;
        }

        slow = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }
}

力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第4张图片

5. 链表的中间结点(简单)

地址:https://leetcode-cn.com/problems/middle-of-the-linked-list/
2021/11/24
AC

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode fast = head, slow = head;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

需要注意的是,如果链表长度为偶数,也就是说中点有两个的时候,我们这个解法返回的节点是靠后的那个节点。
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第5张图片
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第6张图片

6. 相交链表(简单)

地址:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
2021/11/24
做题反思:知道拼接 但是实现时 -> TLE:Time Limit Exceeded
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第7张图片
又一次超时 :此处造成了无限循环
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第8张图片
正解

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1 = headA, p2 = headB;

        while (p1 != p2) {
            if (p1 != null) {
                p1 = p1.next;
            }else {
                p1 = headB;
            }
            if (p2 != null) {
                p2 = p2.next;
            }else {
                p2 = headA;
            }
        }
        return p1;
    }
}

7. 删除链表的倒数第 N 个结点(中等)

地址:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
2021/11/24
做题反思:

  1. 应分两步: 查找到第 N 个结点 再 删除 (两个方法)
  2. 在一个方法中写时,逻辑关系捋不清
    错误代码
    力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第9张图片
    力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第10张图片

2021/11/25
做题反思:

  1. 应返回 dummy 的倒数第 n+1 个结点, 因为 dummy 虽然比原链表长, 但是倒数时却是一样的。
  2. 不过注意我们又使用了虚拟头结点的技巧,也是为了防止出现空指针的情况,比如说链表总共有 5 个节点,题目就让你删除倒数第 5 个节点,也就是第一个节点,那按照算法逻辑,应该首先找到倒数第 6 个节点。但第一个节点前面已经没有节点了,这就会出错。
    但有了我们虚拟节点 dummy 的存在,就避免了这个问题,能够对这种情况进行正确的删除。

正确解法:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 虚拟头结点
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        // 代码规范: n + 1
        ListNode node = findN(dummy, n + 1);
        node.next = node.next.next;
        // 应返回 dummy.next 而非 head 
        return dummy.next;
    }
    
    // 有无 public 均可, 方法名写成:findFromEnd 表达更准确 
    ListNode findN(ListNode head, int n) {
        ListNode fast = head, slow = head;

        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7_第11张图片

你可能感兴趣的:(数据结构与算法,链表,算法,leetcode)