问题描述
- Given a linked list, rotate the list to the right by k places, where k is non-negative.
- Example 1:
Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL
- Example 2:
Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL
问题分析
- 这是一个涉及到循环右移的问题,当循环右移时,将数组或者链表看做成一个环的形式。首尾相连,然后根据循环右移的位数来确定应该从哪里断开。
- 比如Example 1,将链表首尾相连后,若原链表长度不低于2,并且要求循环右移的位数为2,那么原链表中倒数第 2个节点便是循环右移后新链表的头部。又因为我们已经将它连成了一个环,所以必须断开指向新链表头部的next指针。所以必须定位到原链表中倒数第3个节点。
- 如果右移位数
k
大于链表长度,因为是环,只需取模即可k = k % length
- 那么如何找链表中倒数第 K 个节点呢?
剑指offer·-链表中倒数第k个结点中介绍了两种方法,因为此刻我们已经知道了链表长度,所以只需找到正数第n-k+1
个节点即可。
经验教训
- 如何利用环的思想处理循环右移问题。
代码实现
/**
* 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;
}
//统计链表长度,并让curNode最终定位到链尾
ListNode curNode = head;
int length = 1;
while (curNode.next != null) {
curNode = curNode.next;
++length;
}
//连成一个环
curNode.next = head;
//取模处理
k = k % length;
//从前到后找第 n - (k-1) + 1 个节点。该点是新链表的链尾
int count = 1;
curNode = head;
while (count < length - k) {
curNode = curNode.next;
count++;
}
//断开新链尾链头的连接
ListNode newHead = curNode.next;
curNode.next = null;
//返回新链头
return newHead;
}
}