美文网首页
旋转链表

旋转链表

作者: 眼若繁星丶 | 来源:发表于2021-03-27 11:29 被阅读0次

6xglMn.png

https://leetcode-cn.com/problems/rotate-list/

准备工作:

  • 本题用到了一个思想,找到链表倒数第K个位置的节点

  • 使用快慢指针

ListNode slow = head, fast = head;
while (k-- > 0) fast = fast.next; // 这里会执行 K 次, 不确定也可以用 for-loop
while (fast != null) { // 这里的判断条件会让 fast 走到最后的null
    fast = fast.next;
    slow = slow.next;
}
  • 快慢指针指向头,然后快指针先走K步,这样快慢指针间距就是K。然后快慢指针一起走,当快指针走到尾节点时,慢指针所在位置就是链表倒数第 K 位置

链表声明:

class ListNode {
    int val;
    ListNode next;

    ListNode() {
    }

    ListNode(int val) {
        this.val = val;
    }

    ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

解法一:快慢指针

  • 虽然题目说的是旋转链表,但其实找到旋转后的链表的新头节点(倒数第 K 个位置)就可以了
  • 这里要注意,题目给的 K 可能会超过链表的长度,也是官方设下的陷阱。所以一会要处理这个K
  • 并且如果 K 是链表长度的整数倍,则翻转的结果与原链表没区别,直接返回。
public class Solution {
    
    // slow-fast two pointer to find k-th from the bottom
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k == 0) return head;
        // judge k whether an integer multiple
        int sum = 0; // length of the List
        ListNode p = head;
        while (p != null) {
            p = p.next;
            sum++;
        }
        k %= sum;
        if (k == 0) return head;

        ListNode slow = head, fast = head;
        while (k-- > 0) fast = fast.next;
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        ListNode newHead = slow.next;
        slow.next = null;
        fast.next = head; // location of fast pointer is at last of List
        return newHead;
    }

}
  • k %= sum;是刚才说的处理K。也是实际上链表需要旋转的次数。
  • while (fast.next != null)这里跟上面的准备工作里的找到倒数第K个节点不同,区别在于判断条件是 fast.next 。因为本题找到新头节点后,要让链表末尾节点连接到老头节点,然后让新头节点的节点断链。所以实际上处理的是:倒数第K个节点的前一个节点

解法二:闭环

  • 官方解法,先把链表闭环,然后找到倒数第K个位置作为新头节点,同理。
public class Solution {

    // closed cycle and find k-th from the bottom
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k == 0) return head;
        // judge k whether an integer multiple
        int sum = 1;
        ListNode p = head;
        // judging condition is p.next in order to move p to the last node
        while (p.next != null) {
            p = p.next;
            sum++;
        }
        k %= sum;
        if (k == 0) return head;
        // closed cycle
        p.next = head;
        k = sum - k - 1;
        while (k-- > 0) head = head.next;
        ListNode newHead = head.next;
        head.next = null;
        return newHead;
    }

}
  • 涉及到几个细节:
  • 可以在统计链表长度的同时找到末尾节点,后面末尾节点连接到头节点形成闭环操作,复用指针p。所以这里统计长度又不同于解法一,sum初始化为1,while-loop判断对象为p.next,因为不能让p为null,后面会NPE
  • 处理完K之后,在闭环之后开始找到真正的位置,即sum - k - 1,-1 的目的同上,新头节点的前一个节点
  • 因为闭环的关系,所以不用特意去操作尾节点连到老头节点,直接断链返回就可以了。

相关文章

  • leetcode 链表 [C语言]

    21. 合并两个有序链表 合并两个有序链表 61. 旋转链表 (快慢指针) 61. 旋转链表 相关标签 : 链表 ...

  • 链表--旋转链表

    目录[https://www.jianshu.com/p/85e18c21317a] 题号[https://lee...

  • 61. 旋转链表

    61. 旋转链表 问题 给定一个链表,旋转链表,将链表每个节点向右移动 个位置,其中 是非负数。 示例 1: 输...

  • Swift - LeetCode - 旋转链表

    题目 旋转链表 问题: 给定一个链表,旋转链表,将链表每个节点向右移动k个位置,其中k是非负数。 示例: 代码:

  • [LeetCode]61. 旋转链表

    61. 旋转链表给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。示例:输入: 1-...

  • 旋转链表

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

  • 旋转链表

    旋转链表 1.想法: 首先我们可以不每次都找到最后一个元素然后将它作为头结点,即我们得知k后,就可以知道最终的形式...

  • 旋转链表

  • 旋转链表

    题目信息 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。 输入:head = [...

  • 旋转链表

    [https://imgtu.com/i/6xglMn] https://leetcode-cn.com/prob...

网友评论

      本文标题:旋转链表

      本文链接:https://www.haomeiwen.com/subject/broehltx.html