環形鏈表
給定一個鏈表,判斷鏈表中是否有環。
進階:
你能否不使用額外空間解決此題?
思路:兩個指針,一個一次前進兩步一個,如果有一時刻兩個相交說明有環。
時間復雜度:O(n)。兩鏈表只需要循環一遍
空間復雜度:O(1)只需要保存兩個指針
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head == NULL||head->next == NULL)return false;
ListNode*a,*b;
a= head;
b = a->next;
while(true){
if(b->next == NULL)return false;
b = b->next;
if(b->next == NULL)return false;
b = b->next;
a = a->next;
if(b ==a)return true;
}
return false;
}
};
環形鏈表Ⅱ
給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。
說明:不允許修改給定的鏈表。
進階:
你是否可以不用額外空間解決此題?
思路:前半部分同上題,確定有環后,兩個指針繼續一次2步/一次1步地前進,記錄再次相遇時經過的移動的次數n,此時該次數n就為環的節點數,那么將a指向頭部,將b指向a的后第n個節點,同時每次各走一步,當相遇時即為第一個入環點。
時間復雜度:O(n)。
空間復雜度:O(1)
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == NULL||head->next == NULL)return NULL;
ListNode*a,*b;
a= head;
b = a->next;
int i=0;
while(true){
if(b->next == NULL)return NULL;
b = b->next;
if(b->next == NULL)return NULL;
b = b->next;
a = a->next;
if(b ==a){
b = b->next;
b = b->next;
a = a->next;
i++;
while(a != b){
b = b->next;
b = b->next;
a = a->next;
i++;
}
break;
}
}
a = head;
b = a;
while(i>0){
b = b->next;
i--;
}
while(a != b){
a =a->next;
b = b->next;
}
return a;
}
};
相交鏈表
編寫一個程序,找到兩個單鏈表相交的起始節點。
例如,下面的兩個鏈表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在節點 c1 開始相交。
注意:
如果兩個鏈表沒有交點,返回 null.
在返回結果后,兩個鏈表仍須保持原有的結構。
可假定整個鏈表結構中沒有循環。
程序盡量滿足 O(n) 時間復雜度,且僅用 O(1) 內存。
思路:題目只要求返回結果時保持原結構,那么耍個小聰明,運算時將a鏈的尾部指向b的頭部,那么如果不相交就不帶環,相交就變成了如上題的帶環鏈表,交點就是入環點,所以解法如上題,先檢測是否有環(是否相交),再檢測入環點(相交點),最后返回的時候別忘了將鏈表改回來。
時間復雜度:O(n)。
空間復雜度:O(1)
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == NULL || headB == NULL)return NULL;
ListNode*a,*b,*aa;
aa = headA;
b = headB;
while(aa->next != NULL){
aa = aa->next;
}
aa->next = b;
a= headA;
b = a->next;
int i=0;
while(true){
if(b->next == NULL){
aa->next = NULL;
return NULL;
}
b = b->next;
if(b->next == NULL){
aa->next = NULL;
return NULL;
}
b = b->next;
a = a->next;
if(b ==a){
b = b->next;
b = b->next;
a = a->next;
i++;
while(a != b){
b = b->next;
b = b->next;
a = a->next;
i++;
}
break;
}
}
a = headA;
b = a;
while(i>0){
b = b->next;
i--;
}
while(a != b){
a =a->next;
b = b->next;
}
aa->next = NULL;
return a;
}
};