這是乙個比較基本的鍊錶問題。總結一下,可以擴充套件為以下幾類問題:
解法:具體**如下:
定義listnode資料結構
public
class listnode
/**
* 判斷單向鍊錶是否有環
*@param phead
*@return
*/public
boolean
hasloopinlistnode(listnode phead)
listnode slow = phead;
listnode fast = phead;
while(slow !=null&&fast.next !=null)
return
false;
}
/**
* 求環的長度
*@param phead
*@return
*/public
intlengthoflooplistnode(listnode phead)
listnode slow = phead;
listnode fast = phead;
//記錄快慢指標第一次相遇之後為起點,直至第二次相遇所走過的步長
int step = 0;
while(slow !=null&&fast.next !=null)
}if(fast==null||fast.next == null)
//此時,fast停留在首次碰撞的節點
while(fast.val != slow.next.val)
return step;
}
又因為fast的速度是slow的兩倍,所以fast走過的距離是slow走過的兩倍,所以,l2 = 2*l1。即有2(a+b) = a+b+c+b。很容易得出,a = c,也就是說,頭指標到連線點的距離,就是快慢指標首次相遇的碰撞點到連線點的距離。
所以在求連線點位置這個問題時,已經在第二問中求出了碰撞點p的位置(圖中為z),則可以讓slow從頭結點開始,fast從碰撞點z開始,每次分別走一步,直至相遇,因為a=c,所以相遇時,一定在連線點y處
/**
* 找出連線點
* @param phead
* @return
*/public listnode getfirstjoin(listnode phead)
listnode slow = phead;
listnode fast = phead;
//找出第一次碰撞的點
while(slow !=null&&fast.next !=null)
}slow = phead;
while(slow.val != fast.val)
return slow;
}
/**
* 求帶環鍊錶長度
*@param phead
*@return
*/public
intgetlooplength(listnode phead)
listnode slow = phead;
listnode fast = phead;
//頭結點到連線點的距離
int lengthtojoin = 0;
//環長度
int lengthofloop = lengthoflooplistnode(phead);
//找出第一次碰撞的點
while(slow !=null&&fast.next !=null)
}slow = phead;
while(slow.val != fast.val)
return lengthofloop+lengthtojoin;
}
鍊錶中的環入口節點
public class 鍊錶中的環入口節點 計算環的長度 int lengthofcycle 1 listnode curnode meetnode while curnode.next meetnode 找出入口節點 利用快慢指標,前者先行lengthofcycle個節點,然後兩者同時前進當fa...
判斷鍊錶是否有環以及尋找環入口
思路 採用 快慢指標 查檢查鍊錶是否含有環。讓乙個指標一次走一步,另乙個一次走兩步,如果鍊錶中含有環,快的指標會再次和慢的指標相遇。這裡需要注意的一點是演算法中迴圈的條件,這是乙個很容易被忽略的細節。1 因為fast指標比slow指標走得快,所以只要判斷fast指標是否為空就好。由於fast指標一次...
判斷鍊錶中的環的入口節點
有乙個單向鍊錶,判斷鍊錶中是否有環,如果有,返回環的入口節點。功能測試 鍊錶中包含或者不包含環,鍊錶有多個或者乙個節點 特殊值測試 頭指標為空 include includeusing namespace std struct listnode listnode hasring listnode h...