【小白爬Leetcode61】1.13 旋转链表 Rotate List
Leetcode 61 m e d i u m \color{#FF7D00}{medium} medium
题目
Description
Given a linked list, rotate the list to the right by k places, where k is non-negative.
Example1:
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
Example2:
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
中文描述
给定一个链表,旋转链表,将链表每个节点向右移动 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
思路: 先遍历一遍链表,连成环,再用顺时针代替逆时针
思路很简单:
-
第一遍遍历先把链表连成环(最后一个节点连到第一个节点上)。
-
用 first 指针指向要return的节点的前一个节点。那么环的顺时针运动实际上就是指针 first 从head开始的逆时针运动。(时针的顺时针转动,恰如表盘的逆时针运动)
-
而众所周知,一个长为M的跑道,逆时针跑N,和逆时针跑N%M是一样的,和顺时针跑(M-(N%M))也是一样的。因此,我只需要让first 指针从原表头出发,顺着链表方向再走
length-(k%length)
步就可以了。
例如:
令M=400m,N=500m,那么:一个400m的跑道,逆时针跑100m,和逆时针跑(500%400)= 100m 是一样的,和顺时针跑(400-(500%400))= 300m 是一样的。 -
但是first走了
length-(k%length)
步之后,需要将first的上一个节点的->next指向NULL,来打破原来的环,这样就需要一个额外的pre指针来记录first的上一个节点。为了避免这种麻烦,让first少走一步,走length-(k%length)-1
步,令res = 循环后的first->next即可
-
最后
return res
。
源代码如下:
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(k==0){return head;}
if(!head){return NULL;}
int length = 1;
ListNode* first = head;
while(head->next)
{
head = head->next;
length ++;
}
head->next = first;
for(int i=0;i<length-(k%length)-1;i++)
{
first = first->next;
}
ListNode* res = first->next;
first->next = NULL;
return res;
}
};
复杂度分析
时间复杂度:O(N)
空间复杂度:O(1),因为只用到几个指针,只需要常数的空间