链表的快慢指针
快慢指针就是定义两根指针,控制移动的速度一快一慢,以此来制造出自己想要的差值。这个差值通常可以让我们找到链表上相应的中间节点。
寻找链表的中间值
寻找链表的中间值常用在链表的归并排序中,分治思想中需要对链表进行分段cut,即找到链表的中间节点,然后进行截断。利用快慢指针问题就变成,快指针移动的速度是慢指针的两倍,所以当快指针只想链表尾节点时,慢指针正好指向链表的中间节点。
public ListNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null) {
slow = slow.next;
fast = fast.next;
if (fast != null) {
fast = fast.next;
}
}
return slow;
}
判断链表中是否有环
快慢指针中,因为每一次移动后,快指针都会比慢指针多走一个节点,所以他们之间在进入环状链表后,不论相隔多少个节点,慢指针总会被快指针赶上并且重合,此时就可以判断必定有环。
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow.equals(fast)) {
return true;
}
}
return false;
}
删除倒数第n个节点
这个问题主要是找出倒数第n个节点,这又回到了长短指针擅长的差值上来,即只需要让快指针的移动速度比慢指针快n个节点,则快指针移动到尾节点时,慢指针便在倒数第n个节点,此时对原链表的next节点设置称next.next节点,相当于删除了这个节点。
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
dummy.next = head;
/** 快指针比慢指针快n个节点*/
ListNode fast = dummy;
for (int i=0; i<n; i++) {
fast = fast.next;
}
ListNode slow = dummy;
while(fast != null && fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}