【面试经典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

写在最后

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

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

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

相关推荐
浮生如梦_1 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer4 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq4 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown4 小时前
【数据结构】选择排序
数据结构·算法·排序算法
青花瓷5 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
观音山保我别报错5 小时前
C语言扫雷小游戏
c语言·开发语言·算法
幺零九零零6 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
TangKenny6 小时前
计算网络信号
java·算法·华为