力扣算法 Java 刷题笔记【链表篇】hot100(一)7

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;
    }
}

在这里插入图片描述

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;
    }
}

在这里插入图片描述
复杂度: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;
    }
}

在这里插入图片描述

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;
    }
}

在这里插入图片描述

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;
    }
}

需要注意的是,如果链表长度为偶数,也就是说中点有两个的时候,我们这个解法返回的节点是靠后的那个节点。
在这里插入图片描述
在这里插入图片描述

6. 相交链表(简单)

地址:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
2021/11/24
做题反思:知道拼接 但是实现时 -> TLE:Time Limit Exceeded
在这里插入图片描述
又一次超时 :此处造成了无限循环
在这里插入图片描述
正解

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. 在一个方法中写时,逻辑关系捋不清
    错误代码
    在这里插入图片描述
    在这里插入图片描述

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;
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46644403/article/details/121496209