力扣 142.环形链表II 给定一个链表,返回链表开始入环的第一个节点。(Java)

题目描述

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表。

进阶:

你是否可以使用 O(1) 空间解决此题?

原题链接: 环形链表II.

解题思路

一、哈希表

依次遍历整个链表,并创建一个哈希表来存储遍历过的节点,当要存入的节点已经存在于哈希表中,返回该节点即可。若遍历到某节点的next节点为null,说明链表没有环,遍历结束,返回null。
该方法最易于想到,但需要额外的存储空间存遍历过的节点。

二、快慢指针

定义两个指针,一个慢指针,一个快指针,慢指针一次走一步,快指针一次走两步,若两个指针相遇了则有环,没有相遇则无环。初始时,慢指针指向head,快指针也指向head。
当快指针的next节点为null或者快指针本身节点为null时,说明该链表没有环,遍历结束,返回null。如果链表有环,那么快慢指针一定会相遇(比如操场套圈,一定会在某个地方相遇),指向同一个节点,当指向同一个节点时,说明该链表有环。
在这里插入图片描述
有环的情况:
当慢指针p走过a时(假设此时的p为入环的第一个节点,如图),快指针q走过2a,假设环剩下的为x,从此时开始,慢指针p走过x,q走过2x,正好在距离入环的第一个节点x处两指针相遇。相遇时,慢指针p一次走一步的速度向入环的第一个节点走a(环一共a+x)步,若此时声明一个指针指向head,也以一次一步的速度向入环的第一个节点,距离也为a,则两个指针相遇的点就是入环的第一个节点。
即使a>环的长度也满足该说法,可自行稍加理解。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null){
            //空链表 无环 返还null
            return null;
        }
        //慢指针
        ListNode p = head;
        //快指针
        ListNode q = head;
        //保证不会对空进行操作,避免出现段错误,引发程序崩溃
        while(q!=null && q.next!=null){
            p = p.next;
            q = q.next.next;
            if(p == q){
                //快慢指针相遇
                //将快指针重新赋值,用来找入环的第一个节点
                q = head;
                while(p != q){
                    p = p.next;
                    q = q.next;
                }
                //直到p==q,退出while循环,找到入环的第一个节点
                return p;
            }
        }
        //循环结束,有null,说明无环。
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
判断一个链表是否是另一个链表的子序列是一道常见的问题。对于这个问题,我们可以使用双指针的方法来解决。双指针一个指向主链表一个指向子序列链表。我们同时遍历两个链表,比较指针指向的节点是否相同。如果相同,我们就同时向后移动两个指针;如果不相同,我们只移动主链表的指针。当子序列链表遍历完毕时,说明所有的节点都匹配成功,那么它是主链表的子序列;如果主链表遍历完毕,而子序列链表还没有遍历完,说明子序列链表中的节点没有完全匹配,那么它不是主链表的子序列。这种方法的时间复杂度是O(n + m),其中n是主链表的长度,m是子序列链表的长度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [力扣之判断一个链表是否是回文链表](https://blog.csdn.net/chenbaifan/article/details/121450273)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [[力扣] 203.移除链表元素](https://download.csdn.net/download/weixin_38667920/13759251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值