寻找中间节点
给定头节点为head的非空单链表,返回链表的中间节点。如果有两个中间节点,而返回第二个中间结点,例如
输入:[1,2,3,4,5] >>> 输出:3
输入:[1,2,3,4,5,6] >>> 输出:4
思路分析
使用快慢指针。用两个指针slow和fast一起遍历链表。slow一次走一步,fast一次走两步。当fast到达终点,slow必然位于中间
public static Node middleNode(Node head){
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
寻找倒数第K个元素
输入一个链表,输出该链表中的倒数第K个节点,例如
输入:1➡2➡3➡4➡5 ,K=2
返回链表:4➡5
思路分析
用快慢指针,先将fast向后遍历k个节点,slow不变。这时slow和fast间隔了k个节点,之后两个指针同步走,当fast走到尾部空节点时,slow刚好指向链表的倒数第K个节点
不需要判断fast.next !=null
public static Node getKthFromEnd(Node node, int k){
Node slow = node, fast = node;
while (fast != null && k > 0){
fast = fast.next;
k--;
}
while (slow !=null && fast != null) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
旋转链表
给你一个链表的头节点head,旋转链表,将链表每个节点向右移动k个位置,示例
输入:head = [1,2,3, 4,5], k = 2
输出:[4,5,1,2,3]
注意:k的长度是会大于链表长度的,所以要进行判断!(k % len)
思路分析
利用双指针策略找到倒数K的位置{1,2,3}和{4,5},然后将两个链表拼接成{4,5,3,2,1}。参考寻找倒数第K个元素
-
循环拿到链表长度
-
快指针先走K步
-
满指针和快指针同时走。快指针到尾节点时,满指针刚好是要断开的位置,把快指针的节点指向原链表头部,满指针指向的节点断开和下一节点的联系
-
注意:k值会大于length,要判断(k%len)
public static Node rotateRight(Node head, int k) {
int length = 0;
Node temp = head;
//拿到链表长度,判断k是否大于len
while (temp != null) {
temp = temp.next;
length++;
}
//若k==0则不用移动
if (k % length == 0) return head;
Node fast = head, slow = head;
//k若大于len的解决方式
while ((k % length) > 0) {
fast = fast.next;
k--;
}
//快慢指针同时移动,快指针走到链表尾部刚好是断开的位置
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
fast.next = head;
head = slow.next;
slow.next = null;
return head;
}