题目链接:
题目描述:
#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
通过次数77,784 提交次数191,996
分析:
初步分析:
- 处理k:k %= len
- 问题转化成把链表的倒数 k 个节点移到前面
- 如何找倒数第 k 个节点:双指针
关于如何 找到链表的倒数第 k 个节点,之间写过一篇文章:
【链表】LeetCode #19 删除链表的倒数第N个节点(时间复杂度O(n),在所有Java提交中击败了100%的用户)
算法:
- 求出链表的长度
len
; - 对
k
做取余操作;(比如链表长度为3
,k = 4
,相当于旋转了一圈多一个,即把倒数第 1 个节点
移动到链表表头); - 指针
i
指向head
,j
指向正数第k
个数; i, j
同时向后走,由于两者之间相差k
个,当j
走完链表,i
就走到了倒数第k
个(灵活运用两个指针 i, j 之间长度差,根据不同的题目要求,决定 j 走到链表最后一个元素,还是走到 null)。
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
/*
* k %= len
* 问题转化成把链表的倒数 k 个节点移到前面
* 如何找倒数第 k 个节点:双指针
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null || head.next == null) return head;
ListNode i = head, j = head, cur = head;
ListNode dummy = new ListNode(-1);
dummy.next = head;
int len = 0;
while(cur != null){
len++;
cur = cur.next;
}
k %= len;
for(int l = 0; l < k; l++){ j = j.next;}
while(j.next != null){
i = i.next;
j = j.next;
}
j.next = head;
dummy.next = i.next;
i.next = null;
return dummy.next;
}
}
提交截图:
复杂度分析:
- 时间复杂度 O(n)
- 空间复杂度 O(1)