算法通关村第一关—链表经典问题之旋转链表笔记
源码地址:GitHub-算法通关村
题目地址:LeetCode
解题思路:
- 首先检查输入的链表是否为空(
head == null
)或者k
是否为0
。如果是其中之一,直接返回原链表,因为旋转0
次或者对空链表旋转没有任何变化。 - 定义三个指针变量:
temp
、slow
、fast
,它们都初始化为链表的头节点head
。其中,temp
用于最后返回结果,slow
和fast
用于找到旋转后的新头节点。 - 使用一个循环遍历链表,计算链表的长度
len
。此时head
指针被移动到了链表的尾部,用于后续的操作。 - 如果
k
是链表长度len
的倍数,说明旋转后的链表和原链表相同,因此直接返回原链表head
。 - 如果
k
不是链表长度len
的倍数,则需要进行旋转操作。首先,通过一个循环将fast
指针向后移动k
次,即找到旋转后的新头节点的前一个节点。 - 接下来,使用两个指针
slow
和fast
一起移动,直到fast
指针指向链表的最后一个节点。此时slow
指针指向旋转后的新头节点的前一个节点。 - 将
slow
的下一个节点作为新的头节点,将fast
的next
指针指向原链表的头节点,实现链表的旋转。 - 最后,返回新的头节点,即
res
。
/**
* 旋转链表
*
* @param head
* @param k
* @return
*/
public ListNode rotateRight(ListNode head, int k) {
// 1. 判断链表是否为空或k是否为0
if (head == null || k == 0) {
return head;
}
// 2. 定义所需变量结点
ListNode temp = head;
ListNode slow = head;
ListNode fast = head;
int len = 0;
// 3. 求出链表长度
while (head != null) {
head = head.next;
len++;
}
// 4. k如果是链表长度的倍数则相当于没移,直接返回
if (k % len == 0) {
return temp;
}
// 5. 先让快指针走k步
while ((k % len) > 0) {
fast = fast.next;
k--;
}
// 6. 快慢指针一起移动,知道快指针移到最后一个结点
while (fast.next != null) {
slow = slow.next;
fast = fast.next;
}
// 7. 拼接链表
ListNode res = slow.next;
slow.next = null;
fast.next = temp;
// 8. 返回
return res;
}