快慢指针算法是一种常用的技巧,用于解决链表中的问题。通常用于链表的遍历、查找等问题
1. 算法的思想
快慢指针算法的思想是:两个指针以不同的速度遍历链表,从而达到目的。其中,快指针每次移动两个节点,而慢指针每次移动一个节点。
2. 常见应用场景
快慢指针的常见应用场景有:
判断链表是否有环
寻找链表的中点
寻找链表的倒数第k个节点
寻找链表的交点
寻找链表的入环点
计算链表的环的长度‘
3. 具体实现
3.1 应用一 判断链表是否有环
使用双指针算法可以判断链表是否有环。具体来说,我们可以定义两个指针:一个慢指针和一个快指针。慢指针每次移动一步,而快指针每次移动两步。如果链表中有环,那么快指针最终会追上慢指针。如果没有环,那么快指针会到达链表的末尾。
以下是Java代码示例:
public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode slow = head; ListNode fast = head.next; while (slow != fast) { if (fast == null || fast.next == null) { return false; } slow = slow.next; fast = fast.next.next; } return true; }
3.2 寻找链表的中点
使用双指针算法可以寻找链表的中点。具体来说,我们可以定义两个指针:一个慢指针和一个快指针。慢指针每次移动一步,而快指针每次移动两步。当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点。
以下是Java代码示例:
public ListNode findMiddle(ListNode head) { if (head == null) { return null; } ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } return slow; }
3.2 使用双指针算法可以寻找链表的倒数第k个节点
使用双指针算法可以寻找链表的倒数第k个节点。具体来说,我们可以定义两个指针:一个快指针和一个慢指针。快指针先走k步,然后慢指针开始走。当快指针到达链表末尾时,慢指针指向的节点即为链表的倒数第k个节点。
以下是Java代码示例:
public ListNode findKthToLast(ListNode head, int k) {
if (head == null || k <= 0) {
return null;
}
ListNode fast = head;
ListNode slow = head;
for (int i = 0; i < k; i++) {
if (fast == null) {
return null;
}
fast = fast.next;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
3.3 寻找链表的交点
使用双指针算法可以寻找链表的交点。具体来说,我们可以定义两个指针:一个指向第一个链表的头节点,另一个指向第二个链表的头节点。然后,我们同时遍历两个链表,如果两个指针指向的节点相同,则它们相交。如果两个链表长度不同,则我们可以让较长的链表的指针先走若干步,然后再同时遍历两个链表。
以下是Java代码示例:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode pA = headA;
ListNode pB = headB;
while (pA != pB) {
pA = (pA == null) ? headB : pA.next;
pB = (pB == null) ? headA : pB.next;
}
return pA;
}
3.4使用双指针算法可以计算链表的环的长度
使用双指针算法可以计算链表的环的长度。具体来说,我们可以定义两个指针:一个指向链表的头节点,另一个指向链表的头节点。然后,我们同时遍历链表,如果两个指针指向的节点相同,则它们相交。如果链表中存在环,则我们可以让其中一个指针指向链表头,另一个指针处于原位置不动,一人一步地走,直到它们再次相遇。此时,它们所走过的距离即为环的长度。
以下是Java代码示例:
public int getLoopLength(ListNode head) {
if (head == null) {
return 0;
}
ListNode slow = head;
ListNode fast = head;
boolean hasLoop = false;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
hasLoop = true;
break;
}
}
if (!hasLoop) {
return 0;
}
int length = 1;
slow = slow.next;
while (slow != fast) {
slow = slow.next;
length++;
}
return length;
}