LeetCode笔记——61旋转链表

题目:

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

示例 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

思路:首先先找到需要移动的节点的前一个节点,然后依次将需要移动的节点拿下来再接在链表的前端。链表好复杂。。。

代码:

public class Solution {
    public ListNode rotateRight(ListNode head, int n) {
        if (head == null || n < 1) {
            return head;
        }
        ListNode root = new ListNode(0);
        root.next = head;
        ListNode p = root;
        ListNode q = root;
        int count = 0;
        for (int i = 0; i <=n; i++) {
            p = p.next;
            count++;
            if (p == null) {  //移动的距离比链表的长度长
                count--; // 链表中除头结点后数据个数
                n = n % count; // 实际要位置的位数
                // 为重新开始位移做准备
                i = 0; p = head;
            }
        }
        // 找到第一个要交换的结点的前驱
        // q为第一个要交换的结点的前驱
        while (p != null) {
            p = p.next; q = q.next;
        }
        p = q;
        q = root;
        if (p != null && p.next != null) {
            // 有要位移的结点
            ListNode node;
            while (p.next != null) {
                // 摘除结点
                node = p.next;
                p.next = node.next; // 接上结点
                node.next = q.next;
                q.next = node;
                q = node; // 最后一个移动的节点
            }
        }
        return root.next;
    }
}

执行最快的代码:

思路基本上和上面的代码一致,只不过最后链表的处理比上面的简单好理解一些。最后移动节点时是整体进行移动,而不是一个一个地移动。

class Solution {
    /**
     * 前后指针+求余法
     */
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k <= 0) return head;
        ListNode front = head, behind = head;
        int len = 0;//记录链表长度
        //S1. 初始化front指针
        //两种情况:1. k小于链表长度时,直接前进k步;
        //2. k大于链表长度时,首先遍历一边链表,求出链表长度len;然后k%=len;
        //同样再走剩下的k步;最大复杂度是走2N-1。
        //若k<=N;走k步;若N<k<2N-1,走k步;
        //若k>=2N;走k%N+N步;
        while (k-- > 0) {
            front = front.next;//前进一步
            len++;
            if (front == null) {
                k %= len;//降低k是N好几倍情况的复杂度
                front = head;//从头开始走
            }
        }
        //S2. front和behind同时前进;front走到最后一个节点;behind走到前一段的最后一个节点
        if(front == head) return head;
        while (front.next != null) {
            front = front.next;
            behind = behind.next;
        }
        //S3. 连接关系处理
        ListNode newHead = behind.next;//旋转之后的头节点
        front.next = head;
        behind.next = null;
        return newHead;
    }
}

猜你喜欢

转载自blog.csdn.net/chenxy132/article/details/83067827
今日推荐