原题链接: https://leetcode.com/problems/rotate-list/
1. 题目介绍
Given a linked list, rotate the list to the right by k places, where k is non-negative.
给出一个链表,向右循环链表 k 位,k是一个非负整数。
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
2. 解题思路
这道题和 189. Rotate Array很像,只不过是把数组换成了链表。
首先,k可能大于数组的长度,因此需要取 k = k % Count,Count是链表的长度。
我们可以将链表分为两段,前 Count - k 个节点是一段,后k个节点是一段。所谓向右循环k位,就是将这两段位置交换。需要将倒数 k 个节点,放到 Count - k 个节点的前面。
时间复杂度O(n).
实现代码
/**
* 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 ){
return head;
}
int Count = CountNodes(head);
k = k % Count;
//k的值可能大于链表的长度,因此要对k进行取余
//如果k的值为零,意味着不需要改动链表,直接返回
if( k == 0){
return head;
}
//将链表分为两段,前Count-k个节点和后k个节点
//需要将k个节点,放到Count-k个节点的前面。
ListNode assist = new ListNode(0);
assist.next = head;
ListNode cur = assist;
for(int i = 1 ; i <= Count-k ; i++){
cur = cur.next;
}
//现在的cur指向第Count-k个节点,在新链表中它将是最后一个节点,
//用split将其保存
ListNode split = cur;
//在新链表中,第Count-k+1 个节点是第一个节点
assist.next = cur.next;
while(cur.next != null){
cur = cur.next;
}
//cur现在指向链表的最后一个节点,在新链表中它将是第k个节点,
cur.next = head;
//将新链表的最后一个节点指向null
split.next = null;
return assist.next;
}
//计算链表总节点数
public int CountNodes(ListNode root){
int ans = 0;
while(root != null){
root = root.next;
ans++;
}
return ans;
}
}