如何判断链表有环
节选141.环形链表
给定一个链表,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 如果链表中存在环,则返回 true 。 否则,返回 false 。
方法一:哈希表缓存
用unordered_set
记录访问过的结点,以<ListNode*
作为元素类型,遍历一遍链表再通过哈希表O(1)的查找效率即可。时间复杂度O(n)
,空间复杂度O(n)
class Solution {
public:
bool hasCycle(ListNode* head) {
//基本思想:哈希表,时间复杂度O(n)空间复杂度O(n)
unordered_set<ListNode*> setNode;
while (head != NULL)
{
if (setNode.find(head) == setNode.end())
setNode.insert(head);
else
return true;
head = head->next;
}
return false;
}
};
方法二:快慢指针
把形成环的链表看成是一个跑道,移动速率(遍历速率)
不同的两个指针,再遍历若干次后会相遇,此时再判断指针对应的结点是否指向相同的地址即可,时间复杂度O(n)
,空间复杂度O(1)
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head == nullptr || head->next == nullptr)
return false;
ListNode* fast = head;
ListNode* slow = head;
while(fast != nullptr && fast->next != nullptr){
fast =fast->next->next;
slow = slow->next;
if(slow == fast){
return true;
}
}
return false;
}
};
如何判断两个单链表是否相交,以及相交点
方法一:同一起跑线对比元素
真实的面试题目,取最长的链表,先遍历abs(lenA - lenB)
,再遍历比对即可
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lenA = 0, lenB = 0;
ListNode* nodeA = headA, *nodeB = headB;
while(nodeA){
++lenA;
nodeA = nodeA->next;
}
while(nodeB){
++lenB;
nodeB = nodeB->next;
}
if(lenA >= lenB){
int dif = lenA - lenB;
while(dif--) headA = headA->next;
}
else{
int dif = lenB - lenA;
while(dif--) headB = headB->next;
}
while(headA && headB){
if(headA == headB) return headA;
headA = headA->next;
headB = headB->next;
}
return nullptr;
}
};