day4
周一啦,上午打起精神刷题!
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.
分析
方法一:
在依次遍历数列时,可用一个Hash Table记录当前元素的位置信息,如果遍历过程中某一位置重复出现,则数列中存在循环结构,输出true;如果遍历到最后未出现重复位置,且光标指向null,则数列中没有循环结构,输出false。
方法二:
可用龟兔赛跑法(自命名),意思是两个速度不一样的点如果在一个存在循环结构的路上奔跑,他们将会二次相遇,如果不存在循环结构,因为速度差异,他们将渐行渐远,快的一个将提前变成空指针。
代码
java
/**
* 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) {
Set<ListNode> s = new HashSet<>();
while(head != null){
if(s.contains(head)){
return true;
}else{
s.add(head);
}
head = head->next;
}
return false;
}
}
// 方法二
public class Solution {
public boolean hasCycle(ListNode head) {
if(null == head || null == head->next){
return false;
}
ListNode slow = head;
ListNode fast = head->next;
while(slow != fast){
// 此处用fast判断,快没问题,慢一点没问题
if(null == fast || null == fast->next){
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
}
c++
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() :val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *slow = head;
ListNode *fast = head;
while (slow && fast) {
slow = slow->next;
fast = fast->next->next;
if (fast == slow) {
return true;
}
}
return false;
}
};
int main() {
Solution solution;
ListNode *head = new ListNode(3,new ListNode(2,new ListNode(0,new ListNode(-4,nullptr))));
head->next->next->next->next = head->next;
if (solution.hasCycle(head)) {
cout << "yes!" << endl;
}
else {
cout << "no!" << endl;
}
return 0;
}
时间复杂度和空间复杂度分析
方法一:
时间复杂度 | 空间复杂度 |
---|---|
O(n) | O(n) |
最多访问一遍列表中的n个结点,而将一个结点加入哈希表仅用O(1),所以整体时间复杂度为O(n);
空间复杂度取决于加入哈希表的元素个数,最多包含n个,所以空间复杂度为O(n)。
方法二:
时间复杂度 | 空间复杂度 |
---|---|
O(n) | O(1) |
总结点数设为n,非循环N步,循环n-N步,速度差为1,则有循环的情况下,时间复杂度为O(N+(n-N)/1),即为O(n);无循环的情况下,时间为fast遍历完所花时间:O(n);
此方法仅用到两个结点,即fast和slow,为常数级,所以空间复杂度为O(1)。
心得
找更优方法!