Leetcode [141, 142] Linked List Cycle,java解法

计算机网络Wireshark实验(西安交通大学) 实验名称 计算机网络Wireshark实验 实验日期 2021 年 5 月 17 日 实验地点 XJTU 阅读详情

141 Linked List Cycle 

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

Approach #1 Hash Set

public boolean hasCycle(ListNode head) {
    Set<ListNode> nodesSeen = new HashSet<>();
    while (head != null) {
        if (nodesSeen.contains(head)) {
            return true;
        } else {
            nodesSeen.add(head);
        }
        head = head.next;
    }
    return false;
}

Complexity analysis

  • Time complexity : O(n). We visit each of the nn elements in the list at most once. Adding a node to the hash table costs only O(1)time.

  • Space complexity: O(n). The space depends on the number of elements added to the hash table, which contains at most nn elements. 

Approach #2 Two Pointers

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) return false;
        // unlike int index in arrays, we now use Listnode as pointers
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast.next != null && fast.next.next != null) {
            if (slow == fast) return true;
            
            slow = slow.next;
            fast = fast.next.next;
        }
        
        return false; 
    }
}

Complexity analysis

  • Time complexity : O(n). Let us denote nn as the total number of nodes in the linked list. To analyze its time complexity, we consider the following two cases separately.

    • List has no cycle:
      The fast pointer reaches the end first and the run time depends on the list's length, which is O(n)O(n).

    • List has a cycle:
      We break down the movement of the slow pointer into two steps, the non-cyclic part and the cyclic part:

      1. The slow pointer takes "non-cyclic length" steps to enter the cycle. At this point, the fast pointer has already reached the cycle. \text{Number of iterations} = \text{non-cyclic length} = NNumber of iterations=non-cyclic length=N

      2. Both pointers are now in the cycle. Consider two runners running in a cycle - the fast runner moves 2 steps while the slow runner moves 1 steps at a time. Since the speed difference is 1, it takes \dfrac{\text{distance between the 2 runners}}{\text{difference of speed}}difference of speeddistance between the 2 runners​ loops for the fast runner to catch up with the slow runner. As the distance is at most "\text{cyclic length K}cyclic length K" and the speed difference is 1, we conclude that
        \text{Number of iterations} = \text{almost}Number of iterations=almost "\text{cyclic length K}cyclic length K".

    Therefore, the worst case time complexity is O(N+K), which is O(n)O(n).

  • Space complexity : O(1). We only use two nodes (slow and fast) so the space complexity is O(1)

 

142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Note: Do not modify the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

Approach #1 Hash Table

public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> visited = new HashSet<ListNode>();

        ListNode node = head;
        while (node != null) {
            if (visited.contains(node)) {
                return node;
            }
            visited.add(node);
            node = node.next;
        }

        return null;
    }
}

Complexity Analysis

  • Time complexity : O(n)O(n)

    For both cyclic and acyclic inputs, the algorithm must visit each node exactly once. This is transparently obvious for acyclic lists because the nnth node points to null, causing the loop to terminate. For cyclic lists, the if condition will cause the function to return after visiting the nnth node, as it points to some node that is already in visited. In both cases, the number of nodes visited is exactly nn, so the runtime is linear in the number of nodes.

  • Space complexity : O(n)O(n)

    For both cyclic and acyclic inputs, we will need to insert each node into the Set once. The only difference between the two cases is whether we discover that the "last" node points to null or a previously-visited node. Therefore, because the Set will contain nn distinct nodes, the memory footprint is linear in the number of nodes.

Approach #2 Floyd's Tortoise and Hare

public class Solution {
    private ListNode getIntersect(ListNode head) {
        ListNode tortoise = head;
        ListNode hare = head;

        // A fast pointer will either loop around a cycle and meet the slow
        // pointer or reach the `null` at the end of a non-cyclic list.
        while (hare != null && hare.next != null) {
            tortoise = tortoise.next;
            hare = hare.next.next;
            if (tortoise == hare) {
                return tortoise;
            }
        }

        return null;
}

    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }

        // If there is a cycle, the fast/slow pointers will intersect at some
        // node. Otherwise, there is no cycle, so we cannot find an entrance to
        // a cycle.
        ListNode intersect = getIntersect(head);
        if (intersect == null) {
            return null;
        }

        // To find the entrance to the cycle, we have two pointers traverse at
        // the same speed -- one from the front of the list, and the other from
        // the point of intersection.
        ListNode ptr1 = head;
        ListNode ptr2 = intersect;
        while (ptr1 != ptr2) {
            ptr1 = ptr1.next;
            ptr2 = ptr2.next;
        }

        return ptr1;
    }
}

Complexity Analysis

  • Time complexity : O(n)O(n)

    For cyclic lists, hare and tortoise will point to the same node after F+C-hF+C−h iterations, as demonstrated in the proof of correctness. F+C-h \leq F+C = nF+C−h≤F+C=n, so phase 1 runs in O(n) time. Phase 2 runs for F < nF<n iterations, so it also runs in O(n) time.

    For acyclic lists, hare will reach the end of the list in roughly \dfrac{n}{2}2n​iterations, causing the function to return before phase 2. Therefore, regardless of which category of list the algorithm receives, it runs in time linearly proportional to the number of nodes.

  • Space complexity : O(1)

    Floyd's Tortoise and Hare algorithm allocates only pointers, so it runs with constant overall memory usage.

三、 关于链表Linked List

设计一个单链表:

/**
 * A singly linked list with a left sentinel node.
 */
class MyLinkedList {

	/** A very simple node class. */
	private static class Node {
		int val;
		Node next;
	}

	// Predecessor of the first element
	private Node headPred;
	// Predecessor of the tail
	private Node tailPred;
	private int length;

	/** Initialize your data structure here. */
	public MyLinkedList() {
		headPred = new Node();
		tailPred = headPred;
		length = 0;
	}

	/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
	public int get(int index) {
		if ((index < 0) || (index >= length)) {
			return -1;
		}
		return findPred(index).next.val;
	}

	/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
	public void addAtHead(int val) {
		if (length == 0) {
			addAtTail(val);
		} else {
			addAfter(headPred, val);
		}
	}

	/** Append a node of value val to the last element of the linked list. */
	public void addAtTail(int val) {
		addAfter(tailPred, val);
		tailPred = tailPred.next;
	}

	/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
	public void addAtIndex(int index, int val) {
		if (index < 0) {
			addAtHead(val);
		} else if (index == length) {
			addAtTail(val);
		} else if ((index >= 0) && (index < length)) {
			addAfter(findPred(index), val);
		}
	}

	/** Delete the index-th node in the linked list, if the index is valid. */
	public void deleteAtIndex(int index) {
		if ((index >= 0) && (index < length)) {
			Node pred = findPred(index);
			if (index == length - 1) { // Remove last element
				// Move tail to the left
				tailPred = pred;
			}
			pred.next = pred.next.next;
			--length;
		}
	}

	/** Return the predecessor of the index-th node. */
	private Node findPred(int index) {
		Node pred = headPred;
		for (int i = 0; i < index; ++i) {
			pred = pred.next;
		}
		return pred;
	}

	/** Add an element after the given node. */
	private void addAfter(Node pred, int val) {
		Node node = new Node();
		node.val = val;
		node.next = pred.next;
		pred.next = node;
		++length;
	}
}

 

prometheus 从入门到精通(史上最全) Prometheus(由go语言开发)是一套开源的监控&报警&时间序列(按照时间排序)数据库的组合。因为kubernetes(俗称k8s)的流行带动了prometheus的发展。它可以监控主机,服务,容器,支持多种exporter采集数据,还支持pushgateway进行数据上报,Prometheus性能足够支撑上万台规模的集群。原文链接:https://blog.youkuaiyun.com/qq_45277554/article/details/130917620时间序列数据。 阅读详情

相关推荐

黑客渗透测试后门隐藏技术揭秘

本文介绍了在授权渗透测试中隐藏后门文件(muma.exe)的多种技术手段。主要包括:通过WinRAR自解压脚本将后门与正常程序捆绑实现双开;利用系统自动运行目录和注册表实现开机自启;修改文件图标伪装成常用软件;将文件存放在冷门系统目录;设置系统+隐藏双重属性增强隐蔽性。此外还涉及对抗安全软件的加壳(UPX)、免杀(msfvenom编码)技术,以及进程注入、日志清除等运行隐藏方法。所有技术仅限合法授权测试使用,未经授权使用将面临法律责任。

m0_60781580的博客 1040

LeetCode—linked-list-cycle(检测是否有环)—Java

题目描述:Given a linked list, determine if it has a cycle in it.Follow up:Can you solve it without using extra space?思路解析:这个只需要快慢指针的方法就可以检测是否有环。代码:/** * Definition for singly-linked list. * class ListNo...

Lynn_Baby的博客 394

Linux 系统管理员必备:Chrome 企业版离线部署全攻略(含 RPM/DEB 双版本)

本文详细介绍了Linux系统管理员如何离线部署Chrome企业版,涵盖RPM和DEB双版本。从获取官方离线安装包到静默安装、权限配置及企业级策略管理,提供全流程解决方案,特别适合Ubuntu等DEB系系统管理员参考。

f9g0h的博客 483

LeetCode----Linked List Cycle

Linked List Cycle Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space? 分析: 判断一个链表是否含有环。 使用弗洛伊德循环检测法。时间复杂度为O(n)。 算法详解如下:

whiterbear的专栏 875

nRF52840 低功耗蓝牙开发指南:从硬件架构到物联网应用实战

本文深入解析nRF52840低功耗蓝牙芯片的硬件架构与开发实践,涵盖从开发环境搭建到BLE协议栈开发的详细指南。通过实战案例分享低功耗优化技巧,帮助开发者高效实现物联网应用,特别适合智能家居和工业场景。

d3e4f的博客 415

【逆向实战】Unity游戏资源提取与解密全攻略:从AssetBundle到libil2cpp.so的破解技巧

本文详细介绍了Unity游戏资源提取与解密的完整流程,涵盖从AssetBundle到libil2cpp.so的破解技巧。通过AssetStudio和Il2CppDumper等工具,读者可以学习如何提取未加密资源、处理加密文件,并掌握动态dump技术。文章还提供了自动化脚本编写和常见问题解决方案,帮助逆向工程爱好者高效完成资源提取任务。

weixin_29012765的博客 1046

Linked List Cycle(判断链表是否有环)-python

Given a linked list, determine if it has a cycle in it.解答:定义两个指针分别从链表头部开始,一个指针每次走一步,另一个指针每次走两步,若两个指针所指的值相等,则说明有环,否则没环;要注意指针所指之处是否为空class Solution(object):    def hasCycle(self, head):        """      ...

qq_22179091的博客 1002

Python高阶爬虫:逆向工程模拟Wind/同花顺等金融终端数据抓取

本文详细阐述了模拟金融数据终端进行数据抓取的全套技术方案。我们从法律合规性讲起,选择了Playwright作为核心自动化工具,通过两个实战案例(同花顺网页版和Wind桌面版)演示了从分析、模拟到数据解析的完整流程,并进一步介绍了构建健壮爬虫系统所需的高级技巧。我们的策略是:启动一个由Playwright控制的浏览器,模拟真人登录,然后监听所有网络请求,从中过滤出我们需要的那个数据API。if key in ['f43', 'f169', 'f170', 'f46', 'f60']: # 价格类字段。

2201_76125261的博客 546

LeetCode 之 linked-list-cycle【检测链表中是否有环】

题目: Given a linked list, determine if it has a cycle in it.   Follow up:   Can you solve it without using extra space?   思路一:要达到的目的,检测链表中是否有环,首先第一个思路可以是遍历整个链表,并标记访问过的节点,如果重复访问了某个节点,说明该链表中有环。该思路实现简单,...

李滚滚的博客 557

001、NPU是什么?为什么嵌入式设备需要它?

本文通过作者调试工业相机板卡的经历,引出嵌入式设备为何需要NPU(神经网络处理器)的探讨。文章对比了CPU和NPU的设计哲学差异,指出NPU通过专用乘加器阵列和优化的数据流,能高效处理神经网络运算。作者分析了嵌入式设备使用NPU的三大优势:算力提升、功耗降低和实时性保障,并介绍了三类常见NPU形态。通过一个YOLOv5模型调试案例,揭示了NPU使用中的常见陷阱,最后给出五条实用建议,强调理解NPU原理和局限的重要性。文章生动展现了NPU在嵌入式AI应用中的关键作用。

m0_50546716的博客 125

海上通信技术发展与研究综述

通过对海浪模型、节点运动特性、天线辐射特性等进行特征深度学习,考虑改变有效链路的持续时间、业务类型和容量的区别,以及卫星和节点的仰角等,改变通信策略,设计动态波束成形算法,优化折中浮标天线增益和波束宽度,适应海上环境,尤其是海浪运动时变的特性。目前的海上通信系统,同时包括海上无线通信系统、卫星通信系统、岸基通信系统、船载基站通信系统、空中基站通信系统等不同方法组成的通信系统来满足不同的需求,如海上无线通信系统通信成本低廉、卫星通信系统具有广域的覆盖范围、岸基通信网络可以实现数据高速传输。

weixin_70923796的博客 1000

LeetCode Top 100 Liked Questions 141. Linked List Cycle (Java版; Easy)

welcome to my blog LeetCode Top 100 Liked Questions 141. Linked List Cycle (Java版; Easy) 题目描述 Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked list, we...

littlehaes的博客 179

向华为学习——解读158页 华为敏捷园区网技术解决方案【附全文阅读】

华为敏捷园区网解决方案通过策略随行和体验随身技术,满足移动办公场景下的网络需求。该方案采用敏捷交换机和防火墙自动执行策略配置,实现用户身份认证与业务策略的无缝衔接,且策略配置与IP地址解耦,简化了管理流程。相比传统技术,该方案有效解决了用户分级、QoS保障、无线接入等关键问题,确保用户在移动过程中获得一致的网络体验。

cdfunlove的博客 379

(Leetcode 142)Linked List Cycle (II) (快慢指针详解)

Leetcode141题和142题很相似,都涉及到了快慢指针的算法。快慢指针就是设置两个指针,一个快指针,一个慢指针来达到解题的目的。下面分为以下几个模块来讲解: 解第141题解第142题为什么快指针一定要设置为慢指针的2倍快慢指针的拓展应用 一、Leetcode 141题 题目为:Linked List Cycle Given a linked list, determi

willduan的博客 1万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

(Leetcode 142)Linked List Cycle (II) (快慢指针详解)

Leetcode141题和142题很相似,都涉及到了快慢指针的算法。快慢指针就是设置两个指针,一个快指针,一个慢指针来达到解题的目的。下面分为以下几个模块来讲解: 解第141题 解第142题 为什么快指针一定要设置为慢指针的2倍 快慢指针的拓展应用 一、Leetcode 141题 题目为:Linked List Cycle Given a linked list, determine i...

zhunode的探索 330

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

LeetCode-141.142. Linked List Cycle (JAVA)链表找环

LeetCode-141.142. Linked List Cycle (JAVA)链表找环

mine_song的博客 936

LeetCode 141 Linked List Cycle 142 Linked List Cycle II

问题描述: 解答: public class Solution { public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode slow=head;...

susuxuezhang的博客 271

leetcode 141. Linked List Cycle 快慢指针

题意 返回是否有环 解1 // 全部存下来 // Runtime: 3 ms, faster than 19.84% of Java online submissions for Linked List Cycle. //Memory Usage: 39.2 MB, less than 16.56% of Java online submissions for Linked List Cycle. public boolean hasCycle(ListNode head)

1 141

leetcode 142. Linked List Cycle II 龟兔赛跑(循环指针)

上一题 题意 如果有环,找出环第一个出现的节点,如果没有,返回null。 解1 空间O(N) // Runtime: 3 ms, faster than 23.27% of Java online submissions for Linked List Cycle II. //Memory Usage: 39.7 MB, less than 5.94% of Java online submissions for Linked List Cycle II. public ListNo

1 180

LeetCode 142. 环形链表 II(Linked List Cycle II)

142. 环形链表 II 142. Linked List Cycle II 题目描述 给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回 null。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。 说明: 不允许修改给定的链表。 LeetCode142. Linked List Cycl...

weixin_30788731的博客 111

【leetcode】142. Linked List Cycle II

第142是第141的一个升级版, Given a linked list, determine if it has a cycle in it. 141要求的是查出是否存在有一个链表的循环; Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

SherryWay的博客 263

LeetCode 142. Linked List Cycle II(快慢指针)

Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To represent a cycle in the given linked list, we use an integer pos which represen...

da_kao_la的博客 275

C语言快慢指针,【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked L...

引入快慢指针经常用于链表(linked list)中环(Cycle)相关的问题。LeetCode中对应题目分别是:简介快指针(fast pointer)和慢指针(slow pointer)都从链表的head出发。slow pointer每次移动一格,而快指针每次移动两格。如果快慢指针能相遇,则证明链表中有环;否则如果走到头了依然没有相遇,则没有环。快慢指针的具体代码(C++, Python, Ja...

weixin_36403165的博客 263

【LeetCode-面试算法经典-Java实现】【142-Linked List Cycle II(单链表中有环II)】

【142-Linked List Cycle II(单链表中有环II)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】原题  Given a linked list, return the node where the cycle begins. If there is no cycle, return null.   Follow up:   Can you solve

https://github.com/Wang-Jun-Chao 4410

【LeetCode】142. Linked List Cycle II

Difficulty:medium More:【目录】LeetCode Java实现 Description Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull. Note:Do not modify the linked list. Follow...

weixin_30677073的博客 121

LeetCode_LinkedList_142. Linked List Cycle II 环形链表 II(C++/Java)【快慢指针】

目录 一,题目描述 英文描述 中文描述 二,解题思路 三,AC代码 C++ Java 四,解题过程 第一博 一,题目描述 英文描述 Given a linked list, return the node where the cycle begins. If there is no cycle, return null. There is a cycle in a linked list if there is some node in the list that can be

&再见萤火虫&的博客 247

【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycl...

引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题。LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 142. Linked List Cycle II 找到环的起始节点(entry node)位置。 简介 快指针(fast pointer)和慢指针(slow pointer)都从链表的hea...

weixin_30258027的博客 271
上一篇: Leetcode[217, 136, 349, 202] HashTable 小专题 1 HashSet
下一篇: 亚麻 OA 2019 题目
YuanTheCoder
博客等级 码龄9年 2粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值