題目描述
一個鏈表中包含環,請找出該鏈表的環的入口結點。
思路
- hashset,最快的想法;重複檢驗嘛
- 截斷指針;因爲什麼呢?因爲你會發現入口結點有兩個入口,如果從頭開始截斷指針,最後的這個一定是入口結點;
- 神奇的雙指針:其實這個想法我稍微想過,不過步驟比較多,沒想明白;首先我們進入了環中,就可以計算環的節點數目;第二個想法是在一個環中,兩個結點追逐的話,在繞一圈以後,就會相遇;
那對這一題來說:
一個指針在頭,另一個提前移動環節點數目,最後就會相遇;
代碼
//hashset
static public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead==null)
return null;
ListNode node = pHead;
HashSet<ListNode> hashSet = new HashSet<>();
while (pHead!=null)
{
if (hashSet.contains(node))
{
return node;
}
hashSet.add(node);
node = pHead.next;
pHead= node;
}
return null;
}
//截斷
static public ListNode EntryNodeOfLoop1(ListNode pHead)
{
if (pHead==null||pHead.next == null)
return null;
ListNode frontnode = pHead.next;
ListNode backnode = pHead;
while (frontnode!=null)
{
backnode.next = null;
backnode = frontnode;
frontnode =frontnode.next;
}
return backnode;
}
static public ListNode FindMeetingnode(ListNode pHead)
{
if (pHead==null)
return null;
ListNode slow = pHead.next;
if (slow!=null)
return null;
ListNode quick = slow.next;
while (slow!=null&&quick!=null)
{
if (slow==quick)
return slow;
slow = slow.next;
quick = quick.next;
if (slow != quick)
quick=quick.next;
}
return null;
}
static public ListNode EntryNodeOfLoop2(ListNode pHead)
{
ListNode meetingnode = FindMeetingnode(pHead); //獲取相遇節點
if (meetingnode ==null) //相遇節點沒有話,證明沒有環
return null;
int nodesInloop = 1; //環節點數目
ListNode p1 = meetingnode;
while (p1.next!=meetingnode) //計算環節點數目
{
p1 = p1.next;
++nodesInloop;
}
p1 = pHead;
for (int i = 0; i < nodesInloop; i++) { //p1指針向前走環節點數目
p1 =p1.next;
}
ListNode p2 = pHead; //p2指針爲頭結點
while ( p1 !=p2) //這時相遇時就是入口結點;
{
p1 =p1.next;
p2 = p2.next;
}
return p1;
}
收穫
- 神奇的鏈表環,雙指針;