寻找中间结点
LeetCode876 经典的快慢指针问题,用两个指针slow和fast遍历链表
当slow一次走一步,fast一次走两步,当fast到达链表的末尾时,slow一定位于中间
注意事项
1)当遍历为偶数时,需要留意链表返回的是中间靠后的结点
数组返回的是中间靠左的结点
2)链表遍历是从第一个开始,而数组遍历是从第0个开始,所以出现不同情况
public static ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
注意代码细节:不能写成fast.next != null && fast != null,回导致fast.next空指针异常的情况
寻找倒数第K个元素
经典快慢双指针问题
其实就是通过fast指针先走到第k+1结点,令fast指针与slow指针始终保持距离差,当fast走到链表尾部空结点时,slow指针走到链表的倒数第k个节点
public static 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
旋转链表
这道题也是可以通过双指针找到倒数K的位置,然后将链表分成{1,2,3}和{4,5}两个序列,然后在进行拼接,具体实现思路
public static 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++;
}
//当k刚好等于链表长度时直接返回头结点
if (k % len == 0) {
return temp;
}
//让fast指针先走k步,产生间隔
while ((k % len) > 0) {
k--;
fast = fast.next;
}
//fast走到最后一个结点时,slow指向断开位置的前一个
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
//将新链表头指向刚好断开位置
ListNode res = slow.next;
//为了避免形成环
slow.next = null;
//将fast指向的尾结点指向链表头
fast.next = temp;
return res;
}