LeetCode61.旋转链表(2022/10/20)

83 阅读1分钟

本文已参加 新人礼创作礼 活动,一起开启掘金创作之旅

题目描述

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

样例

blablabla

image.png

输入: head = [1,2,3,4,5], k = 2
输出: [4,5,1,2,3]

image.png

输入: head = [0,1,2], k = 4
输出: [2,0,1]

算法1

(快慢指针) O(n)O(n)
  • 由于 k 可能会大于链表总结点数,超过的部分是无意义的,故可以先求出链表的结点总数 n,然后 k 对 n 取余,k %= n
  • 需要完成链表的旋转,需要找到链表的两个结点,倒数第 k + 1个结点,倒数第 k - 1 个结点,如图:

image.png

  • 定义两个指针,分别指向 head,第一个指针 p 先向下移动 k 步, 然后两个指针 p, q 同时向后移动,直到p 的下一个节点为 null,此时的结点 q 就指向了 倒数 k + 1的位置,结点 p 指向了倒数第 k - 1 个位置,下面就可以进行旋转链表了。
  • 首先 p 的下一个结点应该指向 head, 此时 head 变为 q 的下一个结点,最后 q 的下一个结点变为 null;
  • 返回 head

ps: 当链表为空时,结点数为 0,此时取余会出现错误,需要进行特判,当链表为空时,直接放回 null。

Java 代码

/**
 * 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) {
        // 特判,
        if (head == null) return null;
        // 快指针
        ListNode p = head;
        // 慢指针
        ListNode q = head;
        int n = 0;
        // 求结点总数
        while(p != null) {
            p = p.next;
            n ++;
        }
        k %= n;
        p = head;
        while((k--) != 0) {
            p = p.next;
        }
        while(p.next != null) {
            p = p.next;
            q = q.next;
        }
        // 旋转链表
        p.next = head;
        head = q.next;
        q.next = null;
        // 返回结果
        return head;
    }
}