旋转链表
难度:
标签:
题目描述
给你一个链表的头节点 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 * 109
代码结果
运行时间: 52 ms, 内存: 15 MB
/*
* Problem: Rotate a linked list to the right by k positions using Java Streams.
* Note: As Java Streams are typically used for collections, not linked lists, this solution
* manually collects the list elements and then uses Streams for rotation.
* Approach:
* 1. Convert the linked list to a List.
* 2. Calculate the effective rotations needed (k % length).
* 3. Use Java Streams to manipulate the list.
* 4. Reconstruct the linked list from the rotated list.
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class RotateListStream {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || k == 0) return head;
// Convert linked list to list
List<ListNode> nodes = new ArrayList<>();
ListNode current = head;
while (current != null) {
nodes.add(current);
current = current.next;
}
// Calculate effective rotations needed
int length = nodes.size();
k %= length;
if (k == 0) return head;
// Rotate the list using Streams
List<ListNode> rotated = IntStream.concat(
IntStream.range(length - k, length),
IntStream.range(0, length - k))
.mapToObj(nodes::get)
.collect(Collectors.toList());
// Reconstruct the linked list from rotated list
for (int i = 0; i < rotated.size() - 1; i++) {
rotated.get(i).next = rotated.get(i + 1);
}
rotated.get(rotated.size() - 1).next = null;
return rotated.get(0);
}
}
解释
方法:
该题解的思路是先遍历一遍链表,得到链表的长度length。然后将链表首尾相连成环,再计算出需要移动的实际步数 step = length - k % length - 1。最后再遍历 step 步,将环断开,得到旋转后的链表。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在处理极端情况,如链表长度为0或1时,这种算法是否有特别的处理方式,或者算法本身就能够正确处理?
▷🦆
如果k的值远大于链表的长度,例如k是链表长度的数倍,这种情况下算法如何确保高效运行,而不是进行无用的循环?
▷🦆
为什么在计算实际需要移动的步数时使用`length - k % length - 1`,而不是直接使用`k % length`?
▷🦆
在将链表首尾相连后,该算法如何确保在断开正确的节点,以避免链表的破坏或错误连接?
▷相关问题
轮转数组
给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3 输出:[5,6,7,1,2,3,4]
解释: 向右轮转 1 步:[7,1,2,3,4,5,6]
向右轮转 2 步:[6,7,1,2,3,4,5]
向右轮转 3 步:[5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2 输出:[3,99,-1,-100] 解释: 向右轮转 1 步: [99,-1,-100,3] 向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
进阶:
- 尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
- 你可以使用空间复杂度为
O(1)
的 原地 算法解决这个问题吗?
分隔链表
给你一个头结点为 head
的单链表和一个整数 k
,请你设计一个算法将链表分隔为 k
个连续的部分。
每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。
这 k
个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。
返回一个由上述 k
部分组成的数组。
示例 1:

输入:head = [1,2,3], k = 5 输出:[[1],[2],[3],[],[]] 解释: 第一个元素 output[0] 为 output[0].val = 1 ,output[0].next = null 。 最后一个元素 output[4] 为 null ,但它作为 ListNode 的字符串表示是 [] 。
示例 2:

输入:head = [1,2,3,4,5,6,7,8,9,10], k = 3 输出:[[1,2,3,4],[5,6,7],[8,9,10]] 解释: 输入被分成了几个连续的部分,并且每部分的长度相差不超过 1 。前面部分的长度大于等于后面部分的长度。
提示:
- 链表中节点的数目在范围
[0, 1000]
0 <= Node.val <= 1000
1 <= k <= 50