常见的面试题,除了会写代码之外,还要会数学推导,也就是深入理解原理,下面进行说明
1 判断链表是否有环
设置两个指针,一个快指针和一个慢指针,快指针每次向前移动2步,慢指针每次移动1步,由于快指针的移动速度快于慢指针,所以链表如果无环,快指针会先到达末尾,也就是NULL的位置;链表如果有环,快指针会先进入环内,之后会一直在环内移动,快慢指针最终在环内的某个位置相遇。
慢指针p;快指针q;环的长度为C
2 找出单链表中环入口的位置
//两个指针,一个从链表头部开始走,一个从相遇点开始走,相遇的位置即为入口结点
//剑指offer--链表中环的入口结点
public static ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null || pHead.next == null)
return null;
ListNode slow = pHead;
ListNode fast = pHead;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
break;
}
}
if (fast == null || fast.next == null) {
return null;
}
int circleNode = 1;
ListNode p = slow;
while (p.next != slow) {
p = p.next;
circleNode++;
}
slow = pHead;
fast = pHead;
while (circleNode > 0) {
fast = fast.next;
circleNode--;
}
while ( slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
//leetcode142--链表中环的入口结点
//两个指针,一个从链表头部开始走,一个从相遇点开始走,相遇的位置即为入口结点
public static ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode walker = head;
ListNode runner = head;
while (runner != null && runner.next != null) {
walker = walker.next;
runner = runner.next.next;
if (walker == runner) {
break;
}
}
if (runner == null || runner.next == null)
return null;
//walker指向链表头部
walker = head;
while (walker != runner) {
walker = walker.next;
runner = runner.next;
}
return walker;
}
public static void main(String[] args) {
ListNode head = new ListNode(0);
ListNode p1 = new ListNode(1);
ListNode p2 = new ListNode(2);
ListNode p3 = new ListNode(3);
ListNode p4 = new ListNode(4);
ListNode p5 = new ListNode(5);
head.next = p1;
p1.next = p2;
p2.next = p3;
p3.next = p4;
p4.next = p5;
p5.next = p3;
ListNode p = detectCycle(head);