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
这道题是将链表右shift,尾部的移到head前面,shift k次
因为是单向链表,只有head指针,而没有tail,所以要找到最右边的元素,必须从head一直走到最后的null前面一个元素,复杂度O(N),shift k次就需要访问最右边的元素k次,有没有更简便一些的方法,当然有。
观察第一个例子,链表长度5,shift k=2次,就是把最后两个元素移到前面对不对
再看第二个例子,链表长度3,shift k=4次,转来转去,当转到k=3的时候发现没有,链表又回到初始的模样,第四次相当于最后一个元素移到前面,等于说前3次,也就是链表长度次移动是无用功的。我们只需要移动最后k%length 个元素(length指链表长度)。
要移动最后k%length个元素,需要知道length吧,需要知道tail指针(指向最后一个元素的指针),还需要知道从右边数k%length个元素的前一个元素的指针。
所以我们定义两个指针,一个faster,一个slower,让faster先走,走到最后一个元素,这个时候也就知道了length,一石二鸟。
然后根据length计算出k%length, 让slower走到(length-k%length)的元素(因为k%length是从右边数的,从左边就要用length去减)
这时候只需要修改faster.next=head, head=slower.next,slower.next=null就行了
public ListNode rotateRight(ListNode head, int k) {
if(head == null) {
return null;
}
if(k == 0) {
return head;
}
ListNode faster = head;
ListNode slower = head;
int length = 1;
while(faster.next != null) {
faster = faster.next;
length++;
}
for(int i = 1; i < (length - k % length); i++) {
slower = slower.next;
}
faster.next = head;
head = slower.next;
slower.next = null;
return head;
}
或者如下
public ListNode rotateRight(ListNode head, int k) {
if(head == null || head.next == null || k == 0) return head;
ListNode tail = head;
ListNode newTail = head;
int length = 1;
int steps = 0;
while(tail.next != null) {
tail = tail.next;
length ++;
}
steps = length - k % length - 1;
while(steps > 0) {
newTail = newTail.next;
steps --;
}
tail.next = head;
head = newTail.next;
newTail.next = null;
return head;
}