LeetCode 第 61 题旋转链表

简介: LeetCode 第 61 题旋转链表

题目


旋转链表


给你一个链表的头节点 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


题解


解题分析


解题思路


  1. 如果链表的长度为 n, 当我们向右移动的次数 k >= n 时,我们只需要向右移动 k % n 次即可,因为 n 每次移动都会让链表回到原点,新的链表的起点 (n - 1) - (k % n) 个节点(从 0 开始)。


  1. 这样,我们可以先把链表连接成环,然后将指定位置断开。


  1. 具体代码中,我们先计算出链表的长度 n ,并且找到该链表的末尾节点,将其与头部节点相连。这样就得到一个闭合为环的链表。然后我们从新找到新链表的最后一个节点(即原链表的 (n-1)- (k %n) 个节点),将当前闭合为环的链表断开,即可以得到结果。


  1. 有一个可以优化的点就是当 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;
    }
}


提交后反馈结果如下:


网络异常,图片无法展示
|


参考信息



相关文章
|
2月前
【bug记录】旋转链表与力扣报错:member access within null pointer of type ‘struct ListNode‘
【bug记录】旋转链表与力扣报错:member access within null pointer of type ‘struct ListNode‘
|
2月前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
2月前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
2月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
2月前
|
算法
LeetCode第23题合并 K 个升序链表
这篇文章介绍了LeetCode第23题"合并K个升序链表"的解题方法,使用分而治之的思想,通过递归合并链表的方式解决了这个难题。
LeetCode第23题合并 K 个升序链表
|
2月前
|
C++ 索引
leetcode 707.设计链表
本文提供了解决LeetCode 707题"设计链表"的C++实现,包括单链表的节点定义和类方法实现,如添加节点、获取节点值、删除节点等。
|
2月前
|
算法
LeetCode第92题反转链表 II
文章分享了LeetCode第92题"反转链表 II"的解法,通过使用四个指针来记录和更新反转链表段的头部、尾部以及前一个和后一个节点,提供了一种清晰且易于理解的解决方案。
LeetCode第92题反转链表 II
|
2月前
|
存储 算法
LeetCode第48题旋转图像
LeetCode第48题"旋转图像"的解题方法,通过两次翻转操作——先水平翻转再对角线翻转,实现了原地旋转矩阵的效果。
LeetCode第48题旋转图像
|
2月前
|
算法
LeetCode第21题合并两个有序链表
该文章介绍了 LeetCode 第 21 题合并两个有序链表的解法,通过创建新链表,依次比较两个链表的头节点值,将较小的值插入新链表,直至其中一个链表遍历完,再将另一个链表剩余部分接到新链表后面,实现合并。
LeetCode第21题合并两个有序链表
|
2月前
|
算法
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点