LeetCode 环形链表和中间节点(双指针) | Java 刷题打卡

209 阅读3分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接

环形链表(141)

题目描述

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true。 否则,返回 false 。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

进阶

你能用O(1){O(1)}内存解决此问题吗?

注意

  • 链表中节点的数目范围是 [0, 104]
  • -105 <= Node.val <= 105
  • pos-1 或者链表中的一个 有效索引

思路分析

如果链表有环,分别用一个快指针,每次遍历两个,一个慢指针,每次遍历一个,如果存在环,那么这两个指针最终会相交的。

代码展示

时间复杂度是O(n){O(n)},空间复杂度是O(1){O(1)}

public static boolean hasCycle(ListNode head) {
        ListNode quick = head;
        ListNode slow = head;
        while (quick != null && quick.next != null){
            quick = quick.next.next;
            slow = slow.next;
            if (quick == slow){
                return true;
            }
        }
        return false;
    }

链表的中间节点(876)

题目描述

给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 34,我们返回第二个结点。

提示

  • 给定链表的结点数介于 1100 之间。

思路分析

分别用一个快指针,每次遍历两个,一个慢指针,每次遍历一个,快指针达到末尾,慢指针就达到中点了。

代码展示

时间复杂度是O(n){O(n)},空间复杂度是O(1){O(1)}

    public static ListNode middleNode(ListNode head) {  //1,2,3,4,5,6
        //双指针解法
        if (head == null) {
            return null;
        }
        ListNode quick = head;
        ListNode slow = head;
        while (quick != null && quick.next != null) {
            quick = quick.next.next;
            slow = slow.next;
        }
        return slow;

        //单指针解法
        //放到数组中也可以
    }

总结

双指针解法在链表中还是挺常用的,需要好好的掌握。