1.判断链表中是否含有环
- 链表的基础问题,链表的特点是每个节点只知道下一个节点,所以一个指针是无法判断链表中是否含有环。
- 如果链表不含环,那么这个指针最终会遇到空指针null,表示链表到头了,以下代码可以判断链表不含环:
boolean hasCycle(ListNode head){
while(head != null){
head = head.next;
}
return false;
}
- 如果链表中含有环,以上代码会进入死循环。
- 判断单链表是否含环,经典解法就是双指针,一个跑得快,一个跑得慢。***如果含有环,快指针最终会超慢指针一圈,和慢指针相遇,说明链表含有环。***如下代码:
boolean hasCycle(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
return true;
}
}
return false;
}
2.已知链表中含有环,返回环的起始位置
- 当快慢指针相遇时,让任何一个指针再次指向头节点,然后让两个指针以相同速度前进,再次相遇时所在节点就是环的起始位置。看代码:
ListNode detectCycle(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
break;
}
}
fast = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
3.寻找无环单链表的中点
- 一个直接的想法是,先遍历一遍链表,得到链表长度n,然后再一次遍历链表,走到n/2处,就得到了链表的中点。
- 双指针解法:让快指针一次前进两步,慢指针一次前进一步,当快指针为null时,满指针就处于链表的中间位置。当链表的长度为奇数时,慢指针恰巧停在中间位置,当链表的长度为偶数时,慢指针中间偏右位置。代码:
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
4.寻找单链表的倒数第k个元素
- 思路:让快指针先走k步,然后快指针慢指针开始同速前进即可。代码:
ListNode fast = head;
ListNode slow = head;
while(k > 0){
fast = fast.next;
k--;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
return slow;