描述

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

示例 2:

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL

解法:双指针

思路

求解这道题等价于找到链表倒数第 k 个节点,然后将之前的所有节点放到链表的尾部,形成一个新的链表,相当于 LeetCode 第 19 题的进阶版。

对于寻找单向链表的倒数第 \(k\) 个元素问题,可以采用双指针的方法进行求解。

  • 令指针 p1 和指针 p2 均指向表头,然后让指针 p2 跳转 \(k - 1\) 次,此时指针 p2 处于链表的第 \(k\) 个节点

  • 接着,让两个指针同时向链表尾部跳转,直到指针 p2 处于链表的尾部,此时,指针 p1 指向的节点正是链表的倒数第 \(k\) 个节点

在找到倒数第 \(k\) 个节点后,只需要将指针 p2 指向链表头 head、指针 p1 的前一个节点的 next 指针指向 null,最后指针 p1 就是新的链表的表头。

值得注意的是,在这道题中,我们需要找到的是链表的倒数第 \(k+1\) 个节点,从而才能对该节点的 next 指针进行操作(指向 null)。同样地,也需要注意一些边界情况,比如表头 head 为空,k 大于链表长度等。

Java 实现

/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
// 边界情况处理
if (head == null) {
return head;
} // 统计链表长度并对k进行取余操作
int length = 1;
ListNode tmp = head;
while (tmp.next != null) {
tmp = tmp.next;
++length;
}
k = k % length;
if (k == 0) {
return head;
} // 寻找倒数第k+1个节点
ListNode p1 = head, p2 = head;
for (int i = 0; i < k; ++i) {
p2 = p2.next;
}
while (p2.next != null) {
p1 = p1.next;
p2 = p2.next;
} // 旋转链表
ListNode newHead = p1.next;
p1.next = null;
p2.next = head; return newHead;
}
}
// Runtime: 6 ms
// Your runtime beats 100.00 % of java submissions.

Python 实现

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None class Solution:
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
# 边界情况处理
if not head:
return head # 统计链表的长度并对k进行取余操作
tmp, n = head, 1
while tmp.next:
tmp, n = tmp.next, n + 1
k = k % n
if k == 0:
return head # 找到倒数第k+1个节点
p1, p2 = head, head
for i in range(k):
p2 = p2.next
while p2.next:
p1 = p1.next
p2 = p2.next # 旋转链表
new_head = p1.next
p1.next, p2.next = None, head
return new_head # Runtime: 44 ms
# Your runtime beats 99.11 % of python3 submissions.

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\) 表示链表的长度。首先需要迭代 \(n\) 次找出链表的长度,接着让指针 p2 迭代 \(k\) 次到达第 \(k+1\) 个节点的位置,最后还需要迭代 \(n-(k+1)\) 次使得两个指针一个指向链表尾部,一个指向倒数第 \(k+1\) 个节点,而迭代所执行的操作的时间复杂度都是 \(O(1)\) 的,所以最后总的时间复杂度是 \(O(n)\) 的
  • 空间复杂度:\(O(1)\)

【LeetCode题解】61_旋转链表(Rotate-List)的更多相关文章

  1. LeetCode 61:旋转链表 Rotate List

    ​给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. Given a linked list, rotate the list to the right by k pla ...

  2. [Swift]LeetCode61. 旋转链表 | Rotate List

    Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1: I ...

  3. LeetCode - 61、旋转链表

    给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = 2 输出: 4-& ...

  4. LeetCode题:旋转链表

    原题: 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = 2输出: ...

  5. 【LeetCode】61. 旋转链表

    61. 旋转链表 知识点:链表: 题目描述 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置. 示例 输入:head = [1,2,3,4,5], k = 2 输出:[4 ...

  6. leetCode题解之旋转数字

    1.题目描述 X is a good number if after rotating each digit individually by 180 degrees, we get a valid n ...

  7. LeetCode题解-147 对链表进行插入排序

    对链表进行插入排序. 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插 ...

  8. LeetCode题解-147 对链表进行插入排序 Medium

    对链表进行插入排序. 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插 ...

  9. LeetCode 189:旋转数组 Rotate Array

    公众号:爱写bug(ID:icodebugs) 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. Given an array, rotate the array to the ...

随机推荐

  1. CAP 理论

    CAP理论被很多人拿来作为分布式系统设计的金律,然而感觉大家对CAP这三个属性的认识却存在不少误区.从CAP的证明中可以看出来,这个理论的成立是需要很明确的对C.A.P三个概念进行界定的前提下的.在本 ...

  2. uva10905同一思路的两种做法,前一种WA,后一种AC

    这道题应该算一道普通的排序吧,实际上就是另一种形式地比大小,自己最开始是用int型存,后来觉着不行,改用long,结果还是WA,这是第一个程序. 第二个程序是改用string处理,确实比int方便很多 ...

  3. [FAILED]Marking disk "DATA02" as an ASM disk

    执行删除asm磁盘时报错! [root@rac1 grid]# /etc/init.d/oracleasm deletedisk DATA01 /dev/sdc1 Marking disk " ...

  4. ubuntu 修改mysql 5.7数据库密码

    1.vi /ect/mysql/debian 查看debain-sys-maint用户的密码 2.登录mysql 4.切换到mysql数据库,更新 user 表: update user set au ...

  5. 调试 .NET Framework 源代码、.DotNetCore源码

    调试 .NET Framework 源代码..DotNetCore源码 如何调试 .NET Framework 源代码 在 Visual Studio 调试器中指定符号 (.pdb) 和源文件 .NE ...

  6. 【转】Windows Server 2016 安装 IIS 服务时提示指定备用源路径

    原文地址:http://www.codingwhy.com/view/973.html 在Windows Serever 2016中安装IIS的时候,遇到以下提示 是否需要指定备用源路径?一个或多个安 ...

  7. ionic 2.x 3.x 打包 压缩

    大家都知道Ionic项目ionic serve生成的js css 非常庞大,小有1m多,大有几m,文件如此大load页面的时候需要较长时间的加载,特别在生产环境中,灰常不利于用户体验. 因此我们需要进 ...

  8. ubuntu 环境 openstack 源码包制成 deb 包

    安装软件: sudo apt-get install dh-make checkinstall cd neutron sudo checkinstall -D -y -install=no -pkgv ...

  9. [学习笔记]树套树 线段树套Splay

    今天调了一个早上哈哈哈,不过因为\(Splay\),常数比较大 洛谷的评测记录: \(Code\ Below:\) #include <bits/stdc++.h> #define ll ...

  10. Akka(20): Stream:异步运算,压力缓冲-Async, batching backpressure and buffering

    akka-stream原则上是一种推式(push-model)的数据流.push-model和pull-model的区别在于它们解决问题倾向性:push模式面向高效的数据流下游(fast-downst ...