61#旋转链表

题目描述

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

分析

之前做过一个题,是旋转数组,把数组按要求向右循环移位。在旋转数组中,用到了按索引反转数组的一个辅助方法,先把数组整体反转,再分为两部分分别反转,就可以得到结果了。这个方法在链表中就不太适用了,因为链表获取索引很不方便。但是可以借鉴一下大致的思路,依然是把链表分成两部分,把后面一截移到前面一截的前面,不就完成了所谓的循环右移吗?

对此,有两种方法:

  • 双指针+哑节点
  • 单指针

说是两种方法,但其实第二种方法是第一种方法的改进,本质上都是刚才所说的把链表分成两部分,把后面一截移到前面一截的前面。

双指针+哑节点

  1. 新建一个哑节点放在原链表前面
  2. 新建两个指针first,second指向哑节点
  3. 先把first移动到最后一个节点,同时记录下链表的长度len
  4. 再把second移动到第len-k个元素的位置
  5. 执行旋转操作。具体分3个步骤:
    • first跟首结点相连(成环)
    • 哑节点指向新链表的头部second.next
    • 断开second和新链表头部的链接

需要注意的是,k要经过k %= len处理,将旋转转换为单圈。

源码

/**
 * 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 || head.next == null || k == 0) 
            return head;
        ListNode result = new ListNode(0); // 建立哑节点
        result.next = head;
        
        ListNode first = result;
        ListNode second = result;
        int len = 0;
        while (first.next != null){  // first 移到尾节点
            first = first.next;
            len++;
        }
        k %= len; // 转换为单圈
        for (int i = 0; i < len - k; i++){
            second = second.next;
        }
        first.next = result.next; // 旋转操作
        result.next = second.next;
        second.next = null;
        
        return result.next;
    }
}

单指针

单指针实际上是刚才双指针法的简化版,只需要一个辅助指针p。具体步骤如下:

  1. 新建一个指针p,指向链表头部head
  2. 移动p到链表尾部,并记录链表长度
  3. 形成环状(p.next = head
  4. p移动到分界点,即p后面有k个元素
  5. head移动到p.next
  6. 断开phead的链接

跟双指针一样,k要经过k %= len处理,将旋转转换为单圈。

源码

/**
 * 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 || head.next == null || k == 0) 
            return head;
        ListNode p = head;
        int len = 1;
        while (p.next != null){
            p = p.next;
            len++;
        }
        k %= len;
        p.next = head; // 成环
        for (int i = 0; i < len - k; i++){
            p = p.next; // p 移动到分界点
        }
        head = p.next;
        p.next = null;
        
        return head;
    }
}
原文地址:https://www.cnblogs.com/yuzhenzero/p/9633485.html