【面试经典150 | 链表】旋转链表

文章目录

Tag

【单向链表】


题目来源

61. 旋转链表


题目解读

旋转链表,将链表的每个节点向右移动 k 个位置。


解题思路

方法一:遍历

本题题目意思清晰,实现起来比较容易,属于链表基础知识题。

简单题我们仔细做,通过这道简答题来回顾一下单向链表的一些基本操作。

在进行具体的旋转链表操作之前,我们要先统计一下链表的长度 n,为什么?因为要 "将链表的每个节点向右移动 k 个位置",如果 k >= n,我们只需要将链表的每个节点向右移动 k % n 个位置即更新 k %= mk / n 表示要将链表的每个节点向右移动整数个 n 位置,把长度为 n 的链表向右移动 n 个位置等于没有动。

如何求链表的长度 n ?通过迭代枚举单向链表中的所有节点,计数得到链表的长度。具体地,初始化 n = 0,从头结点出发枚举节点,枚举到一个节点 ++n,接着更新当前节点为下一个节点,直到遇到空节点表示链表迭代枚举结束,退出。

将链表的每个节点向右移动 k 个位置,那么原链表的倒数第 k 个节点就是移动后链表的最后一个非空节点,也就是空节点的前一个节点,我们需要找到该节点,然后连上空节点。并且还要将原链表的最后一个非空节点连接到原链表的头结点,这才算完成移动操作(也就是题目说的选择链表)。

在代码实现中,我们先实现的是连接头节点(也就是 官方题解 中说的闭合成环),于是需要遍历原链表找到最后一个非空节点,这个我们可以在计算链表长度的时候将原链表的最后一个非空节点记录下来。然后将移动后链表的最后一个非空节点连接到空节点上,通过从 head 节点往后迭代 n - k - 1 次即可得到移动后链表的最后一个非空节点 lastNode,而 lastNode->next 节点就是我们最终要返回的向右移动后的新链表的头节点。

实现代码

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:

    ListNode* rotateRight(ListNode* head, int k) {
        if(head == nullptr || head->next == nullptr) {
            return head;
        }

        // 计算链表长度
        ListNode* curr = head;
        int n = 1;
        while(curr->next != nullptr) {
            ++n;
            curr = curr->next;
        }

        k %= n;
        if(k == 0) {
            return head;
        }

        // 连接头结点
        curr->next = head;  // 注意此行代码放置的位置

        // 找出移动后链表的最后一个非空节点
        n -= k;
        lastNode = head;
        while(--n) {
            lastNode = lastNode->next;
        }

        // 建立新的头结点
        ListNode* newHead = lastNode->next;
        lastNode->next = nullptr;
        return newHead;
    }
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n), n n n 是链表的长度,最坏情况下,我们需要遍历该链表两次。

空间复杂度: O ( 1 ) O(1) O(1),我们只需要常数的空间存储若干变量。


其他语言

python3

py3 复制代码
class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head or not head.next:
            return head
        
        n = 1
        cur = head
        while cur.next:
            cur = cur.next
            n += 1
        
        k %= n
        if k == 0:
            return head;
        
        cur.next = head
        
        cur = head
        n -= k
        n -= 1
        while n:
            cur = cur.next
            n -= 1
        
        newHead = cur.next
        cur.next = None
        return newHead

写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

相关推荐
Crossoads7 分钟前
【数据结构】排序算法---桶排序
c语言·开发语言·数据结构·算法·排序算法
自身就是太阳15 分钟前
2024蓝桥杯省B好题分析
算法·职场和发展·蓝桥杯
孙小二写代码38 分钟前
[leetcode刷题]面试经典150题之1合并两个有序数组(简单)
算法·leetcode·面试
little redcap44 分钟前
第十九次CCF计算机软件能力认证-1246(过64%的代码-个人题解)
算法
sinat_2765225744 分钟前
C++中move的使用
开发语言·c++
David猪大卫1 小时前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯
Iceberg_wWzZ1 小时前
数据结构(Day14)
linux·c语言·数据结构·算法
微尘81 小时前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
夏天天天天天天天#1 小时前
求Huffman树及其matlab程序详解
算法·matlab·图论
Infedium1 小时前
优数:助力更高效的边缘计算
算法·业界资讯