旋转链表

93 阅读2分钟

这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战

leetcode 旋转链表

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

 

示例 1:

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

示例 2:

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

解题:正常的来讲,如果要移动链表,那就要将链表的每一个节点都往后移动,最后面的节点就移动到链表头部,这种操作比较复杂,所以可以考虑有没有别的办法。节点的移动就是改变next节点的指向,那如果先将链表链接为一个闭环,那么如果要移动k个位置,那只需要将原链表头结点位置移动k个位置到达的节点,然后从这里断开闭环,这就是一个移动后的链表了。假如链表的节点数即链表长度为len,len的范围为0 <= len <= 500,然后如果要移动k个位置,k的范围为0 <= k <= 2 * (10的9次方),那么k是有可能大于等于len的,但是我们可以发现如果是移动k个位置等于len的话,那么链表往后移动len个位置就又回到了原链表的状态,所以其实当k等于len的整数倍就不用移动,就是我们只需移动k % len个位置就可。具体的可以先判断,如果链表不足两个节点或者k为0可以直接返回原链表;然后就遍历链表获取链表节点数,同时找到最后一个节点,判断如果k为链表长度的倍数,那就算真的移动了也是回到原来链表的状态,所以可以直接返回原链表,否则将最后一个节点与头结点相连来形成闭环链表,然后遍历闭环链表到达k位置,将闭环链表从此断开,就形成一个移动k位置后的链表了。

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (k == 0 || head == null || head.next == null) {
            return head;
        }
        int len = 1;
        ListNode tail = head;
        while (tail.next != null) {
            tail = tail.next;
            len++;
        }
        int add = len - k % len;
        if (add == len) {
            return head;
        }
        tail.next = head;
        while (0 < add--) {
            tail = tail.next;
        }
        ListNode ret = tail.next;
        tail.next = null;
        return ret;
    }
}