第一道题目是Leetcode876题,十分经典的双指针问题之一。
什么是双指针,所谓双指针实际上就是指两个不同的变量而已,这两个变量如何变化都是由我们自己来定。
假设我们有两个指针,A与B分别指向实例1中的①这个节点,但是A指针每次只向前走一个位置,第一次到达②,而B指针每次走两个位置,第一次到达③。
接着往前走,A到达③,B到达⑤,而B前面已经没有路可以走了,就意味着到达顶点,这时候A指针指向的就是该链表的中点。
这就是双指针的应用,实际上就是赋予两个指针不同得到运行轨迹,从而得到结果。
附上该题答案,其中A和B指针就可以用slow和fast来替代。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
剑指 Offer 22. 链表中倒数第k个节点 - 力扣(LeetCode)
这里也可以使用快慢双指针,我们先将fast 向后遍历到第 k+1 个节点, slow仍然指向链表的第一个节点,此时指针fast 与slow 二者之间刚好间隔 k 个节点。之后两个指针同步向后走,当 fast 走到链表的尾部空节点时,slow 指针刚好指向链表的倒数第k个节点。
这里需要特别注意的是链表的长度可能小于k,寻找k位置的时候必须判断fast是否为null,这是本题的关键问题之一。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&k>0){
fast=fast.next;
k--;
}
while(fast!=null){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}
利用双指针的思想,我们可以有如下思考:
因为k有可能大于链表长度,所以首先获取一下链表长度len,如果然后k=k % len,如果k == 0,则不用旋转,直接返回头结点。否则:
- 快指针先走k步。
- 慢指针和快指针一起走。
- 快指针走到链表尾部时,慢指针所在位置刚好是要断开的地方。把快指针指向的节点连到原链表头部,慢指针指向的节点断开和下一节点的联系。
- 返回慢指针指向的节点的下一个节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null || k == 0){
return head;
}
ListNode temp = head;
ListNode fast = head;
ListNode slow = head;
int len = 0;
while(head != null){
head = head.next;
len++;
}
if(k % len == 0){
return temp;
}
while((k % len) > 0){
k--;
fast = fast.next;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
ListNode res = slow.next;
slow.next = null;
fast.next = temp;
return res;
}
}