关注
文末的名片达文汐
,回复关键词“力扣源码”,即可获取完整源码!!详见:源码和核心代码的区别
题目详情
给你一个链表的头节点 head
,旋转链表,将链表每个节点向右移动 k
个位置。
示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
示例 2:
输入:head = [0,1,2], k = 4
输出:[2,0,1]
提示:
- 链表中节点的数目在范围
[0, 500]
内 -100 <= Node.val <= 100
0 <= k <= 2 * 10^9
解题思路
- 边界处理:若链表为空或仅有一个节点,或
k=0
,则直接返回原链表。 - 计算链表长度:遍历链表,记录节点数
n
并定位尾节点tail
。 - 链表成环:将尾节点
tail
的next
指向头节点,形成环形链表。 - 计算有效旋转步数:
k
可能远大于链表长度,实际有效旋转步数为k % n
。若结果为0
,则无需旋转,直接断开环并返回原链表。 - 定位新尾节点:新尾节点位于原链表的第
n - k % n - 1
个节点处(从0
开始计数)。从头节点开始移动相应步数即可定位。 - 断开环并返回新头:新头节点为新尾节点的下一个节点。将新尾节点的
next
置为null
,断开环,返回新头节点。
代码实现(Java版)
class Solution {
public ListNode rotateRight(ListNode head, int k) {
// 边界情况:链表为空或只有一个节点
if (head == null || head.next == null || k == 0) {
return head;
}
ListNode tail = head;
int n = 1; // 链表长度,初始为1(至少有一个节点)
// 遍历链表,计算长度并定位尾节点
while (tail.next != null) {
tail = tail.next;
n++;
}
// 链表成环
tail.next = head;
// 计算有效旋转步数
k %= n;
if (k == 0) {
tail.next = null; // 无需旋转,断开环
return head;
}
// 定位新尾节点(位于第 n - k - 1 个位置)
ListNode newTail = head;
for (int i = 0; i < n - k - 1; i++) {
newTail = newTail.next;
}
// 新头节点为新尾节点的下一个节点
ListNode newHead = newTail.next;
newTail.next = null; // 断开环
return newHead;
}
}
代码说明
- 边界处理:直接处理空链表、单节点链表或
k=0
的情况,避免后续计算。 - 链表长度计算:通过遍历链表同时记录节点数
n
和尾节点tail
,时间复杂度为O(n)
。 - 链表成环:将尾节点指向头节点形成环,便于后续旋转操作。
- 有效旋转步数:通过
k %= n
将k
缩减到[0, n-1]
范围内,避免无效旋转。 - 新尾节点定位:从头节点开始移动
n - k - 1
步,时间复杂度为O(n)
。 - 断开环:将新尾节点的
next
置为null
,返回新头节点,完成旋转。