题目
旋转链表
给你一个链表的头节点 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
题解
解题分析
解题思路
- 如果链表的长度为
n
, 当我们向右移动的次数k >= n
时,我们只需要向右移动k % n
次即可,因为 n 每次移动都会让链表回到原点,新的链表的起点(n - 1) - (k % n)
个节点(从 0 开始)。
- 这样,我们可以先把链表连接成环,然后将指定位置断开。
- 具体代码中,我们先计算出链表的长度
n
,并且找到该链表的末尾节点,将其与头部节点相连。这样就得到一个闭合为环的链表。然后我们从新找到新链表的最后一个节点(即原链表的(n-1)- (k %n)
个节点),将当前闭合为环的链表断开,即可以得到结果。
- 有一个可以优化的点就是当
k % n == 0
的时候,新的链表和原链表相同,我们无需做任何处理。
复杂度
- 时间复杂度 O(N)
- 空间复杂度 O(1)
解题代码
题解代码如下(代码中有详细的注释说明):
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode rotateRight(ListNode head, int k) { // 1. 边界值处理 if (head == null || k == 0 || head.next == null) { return head; } // 2. 链表长度计算 int n = 1; // 3. iter 指针指向尾节点 ListNode iter = head; while (iter.next != null) { iter = iter.next; n++; } // 4. 如果 k > n 那么势必要旋转多圈,那么我们只需要旋转有效的 <n 此即可 int add = n - k % n ; // 5. 特殊情况,旋转到原地 if (add == n) { return head; } // 6. 尾节点指向头节点,形成环 iter.next = head; // 7. 实际旋转 while (add-- > 0) { iter = iter.next; } ListNode ret = iter.next; // 8. 去除环 iter.next = null; return ret; } }
提交后反馈结果如下:
网络异常,图片无法展示
|