给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
示例 2:
输入:head = [0,1,2], k = 4
输出:[2,0,1]
提示:
链表中节点的数目在范围 [0, 500] 内
-100 <= Node.val <= 100
0 <= k <= 2 *
1
0
9
10^9
109
思路
这是一道在之前“找到链表倒数第k个节点”问题基础上的题。因为当我们找到了倒数第k个节点,就可以将链表的后半部分和前半部分进行拼接。
考虑到在本题中,k可能会大于链表的长度,可以在每次发现快指针到达结尾时将快指针重新指向head
需要进行几个特殊情况的判断:
如果k=0或后移k次后fast=slow,直接返回head
代码:
public ListNode rotateRight(ListNode head, int k) {
if(head==null||k==0) return head;
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode fast = head;
ListNode fastPre = dummy;
ListNode slow = head;
ListNode slowPre = dummy;
for(int i=0;i<k;i++){
if(fast.next==null){
fast = head;
fastPre = dummy;
}
else{
fast = fast.next;
fastPre = fastPre.next;
}
}
if(fast==slow){
return head;
}
while(fast!=null){
fast = fast.next;
fastPre = fastPre.next;
slow = slow.next;
slowPre = slowPre.next;
}
dummy.next = slow;
fastPre.next = head;
slowPre.next = null;
return dummy.next;
}
实际运行了一下,发现运行时间太长了,仅打败了5%的用户,实在丢人。看到大佬们有更好的解法:
先遍历到链表末尾,将链表头尾相接,同时获得链表的长度n
实际只需要后移k mod n次并在该位置即可
代码
public ListNode rotateRight(ListNode head, int k) {
if(head==null||k==0){
return head;
}
int length=1;
ListNode cur = head;
while(cur.next!=null){
cur = cur.next;
length++;
}
cur.next = head;
int num = length-k%length;
cur = head;
for(int i=0;i<num-1;i++){
cur = cur.next;
}
ListNode result = cur.next;
cur.next = null;
return result;
}
用了这个方法,终于达到了100%!