【LeetCode题解】61_旋转链表(Rotate-List)

目录

  • 描述
  • 解法:双指针
    • 思路
    • Java 实现
    • Python 实现
    • 复杂度分析

描述

给定一个链表,旋转链表,将链表每个节点向右移动 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)\)

原文地址:https://www.cnblogs.com/xugenpeng/p/9914281.html

时间: 2024-10-04 15:58:59

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

Leetcode题解——数据结构之链表

1. 找出两个链表的交点 2. 链表反转 3. 归并两个有序的链表 4. 从有序链表中删除重复节点 5. 删除链表的倒数第 n 个节点 6. 交换链表中的相邻结点 7. 链表求和 8. 回文链表 9. 分隔链表 10. 链表元素按奇偶聚集 链表是空节点,或者有一个值和一个指向下一个链表的指针,因此很多链表问题可以用递归来处理. 1. 找出两个链表的交点 160. Intersection of Two Linked Lists (Easy) 例如以下示例中 A 和 B 两个链表相交于 c1: A

LeetCode 189:旋转数组 Rotate Array

公众号:爱写bug(ID:icodebugs) 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. Given an array, rotate the array to the right by k steps, where k is non-negative. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向右旋转 2 步: [6,7,1,2,3,4,

LeetCode 题解 | 237. 删除链表中的节点

题目描述: 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点. 现有一个链表 --?head =?[4,5,1,9],它可以表示为: 示例 1: 输入: head = [4,5,1,9], node = 5 输出: [4,1,9] 解释: 给定你链表中值为?5?的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 示例 2: 输入: head = [4,5,1,9], node = 1 输出: [4,5,9] 解释: 给定你链表

[LeetCode] Rotate List 旋转链表

Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1->2->3->4->5->NULL and k = 2,return 4->5->1->2->3->NULL. 这道旋转链表的题和之前那道Rotate Array 旋转数组 很类似,但是比那道要难一些,因为链表的值不能通过下表来访问,只能一个一个的

[LeetCode 题解]: Rotate List

Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1->2->3->4->5->NULL and k = 2,return 4->5->1->2->3->NULL. 题意: 翻转链表. 思路: 首先需要读懂题意.题目的描述有问题,应该是将链表的最后k个元素移动到链表的头部. 这道题的本质就是寻找链表的

leetcode 题解:Search in Rotated Sorted Array II (旋转已排序数组查找2)

题目: Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this affect the run-time complexity? How and why? Write a function to determine if a given target is in the array. 说明: 1)和1比只是有重复的数字,整体仍采用二分查找 2)方法二 : 实现:  

leetcode题解:Search in Rotated Sorted Array(旋转排序数组查找)

题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target value to search. If found in the array return its index, otherwise return -1. You may assume no du

(每日算法)LeetCode --- Reverse Linked List II(旋转链表的指定部分)

Reverse Linked List II(旋转链表的指定部分) Leetcode Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. Note: Given m, n sati

61:Rotate List(旋转链表)【链表】【两指针】

题目链接:https://leetcode.com/problems/rotate-list/ /* 题意:给出一个链表,将链表向右旋转k个位置 */ /** *思路:右旋k个位置,相当与将链表从第len-k个位置截断,然后 * 将两截链表交换位置,重新链接成一个链表 * */ struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: