一、题目描述
给你一个链表的头节点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 * 10^9
原题地址:https://leetcode.cn/problems/rotate-list/
二、题目解析
1、首先遍历整个链表,求出链表的长度len。
2、根据题目的提示,k可能很大,远超链表的长度,这样就会导致一种情况,比如 k = 1000,len = 999,每个节点向右移动 1 个节点和向右移动 k = 1000 个节点结果一样,所以进行一个取模的操作可以节省大量的移动操作。
3、接下来设置两个指针 former、latter 均指向链表的头节点,这两个指针的目的是去寻找出旋转之前的尾节点位置、旋转成功之后的尾节点位置。
4、先让former指针先向前移动 k 次,此时,former就和latter相距 k 个节点了。
5、接下来,让former、latter同时向后移动,直到former来到了最后一个节点位置。

6、这个时候,从head到latter有len - k个节点,latter + 1 到 former 有 k 个节点。
7、也就意味着,latter + 1这个节点是移动 k 个节点成功之后的头节点。

8、只需要返回latter + 1后面这个节点newHead,并且断开连接就行了。
三、参考代码
1、Java 代码
//登录AlgoMooc官网获取更多算法图解 //https://www.algomooc.com //作者:程序员吴师兄 //代码有看不懂的地方一定要私聊咨询吴师兄呀 //旋转链表(LeetCode61)//leetcode.cn/problems/rotate-list/ classSolution{ publicListNoderotateRight(ListNodehead,intk){ //边界条件判断 if(head==null){ returnhead; } //1、第一步先要计算出链表的长度来 intlen=0; //2、这里我们设置一个指针指向链表的头节点的位置 ListNodetempHead=head; //3、通过不断的移动tempHead,来获取链表的长度 while(tempHead!=null){ //tempHead不断向后移动,直到为null tempHead=tempHead.next; //每次遍历一个新的节点,意味着链表长度新增1 len++; } //由于题目中的k会超过链表的长度,因此进行一个取余的操作 //比如k=1000,len=999 //实际上就是将链表每个节点向右移动1000%999=1个位置就行了 //因为链表中的每个节点移动len次会回到原位 k=k%len; //4、接下来设置两个指针指向链表的头节点 //这两个指针的目的是去寻找出旋转之前的尾节点位置、旋转成功之后的尾节点位置 //former指针 ListNodeformer=head; //latter指针 ListNodelatter=head; //former指针先向前移动k次 for(inti=0;i< k ; i++){ // former 不断向后移动 former = former.next; } // 这样 former 和 latter 就相差了 k 个节点 // 5、接下来,两个指针同时向后移动,直到 former 来到了最后一个节点位置 while(former.next != null){ // former 不断向后移动 former = former.next; // latter 不断向后移动 latter = latter.next; } // 6、此时,former 指向了最后一个节点,需要将这个节点和原链表的头节点连接起来 former.next = head; // 7、latter 指向的节点的【下一个节点】是倒数第 k 个节点,那就是旋转成功之后的头节点 ListNode newHead = latter.next; // 8、断开链接,避免成环 latter.next = null; // 9、返回 newHead return newHead; } }
2、C++ 代码
classSolution{
public:
ListNode*rotateRight(ListNode*head,intk){
//边界条件判断
if(head==NULL){
returnhead;
}
//1、第一步先要计算出链表的长度来
intlen=0;
//2、这里我们设置一个指针指向链表的头节点的位置
ListNode*tempHead=head;
//3、通过不断的移动tempHead,来获取链表的长度
while(tempHead!=NULL){
//tempHead不断向后移动,直到为NULL
tempHead=tempHead->next;
//每次遍历一个新的节点,意味着链表长度新增1
len++;
}
//由于题目中的k会超过链表的长度,因此进行一个取余的操作
//比如k=1000,len=999
//实际上就是将链表每个节点向右移动1000%999=1个位置就行了
//因为链表中的每个节点移动len次会回到原位
k=k%len;
//4、接下来设置两个指针指向链表的头节点
//这两个指针的目的是去寻找出旋转之前的尾节点位置、旋转成功之后的尾节点位置
//former指针
ListNode*former=head;
//latter指针
ListNode*latter=head;
//former指针先向前移动k次
for(inti=0;i< k ; i++){
// former 不断向后移动
former = former->next;
}
//这样former和latter就相差了k个节点
//5、接下来,两个指针同时向后移动,直到former来到了最后一个节点位置
while(former->next!=NULL){
//former不断向后移动
former=former->next;
//latter不断向后移动
latter=latter->next;
}
//6、此时,former指向了最后一个节点,需要将这个节点和原链表的头节点连接起来
former->next=head;
//7、latter指向的节点的【下一个节点】是倒数第k个节点,那就是旋转成功之后的头节点
ListNode*newHead=latter->next;
//8、断开链接,避免成环
latter->next=NULL;
//9、返回newHead
returnnewHead;
}
};
3、Python 代码
classSolution: defrotateRight(self,head:Optional[ListNode],k:int)->Optional[ListNode]: #边界条件判断 ifnotheadork==0: returnhead #1、第一步先要计算出链表的长度来 _len=0 #2、这里我们设置一个指针指向链表的头节点的位置 tempHead=head #3、通过不断的移动tempHead,来获取链表的长度 whiletempHead: #tempHead不断向后移动,直到为NULL tempHead=tempHead.next #每次遍历一个新的节点,意味着链表长度新增1 _len+=1 #由于题目中的k会超过链表的长度,因此进行一个取余的操作 #比如k=1000,len=999 #实际上就是将链表每个节点向右移动1000%999=1个位置就行了 #因为链表中的每个节点移动len次会回到原位 k=k%_len #4、接下来设置两个指针指向链表的头节点 #这两个指针的目的是去寻找出旋转之前的尾节点位置、旋转成功之后的尾节点位置 #former指针 former=head #latter指针 latter=head #former指针先向前移动k次 foriinrange(0,k): #former不断向后移动 former=former.next #这样former和latter就相差了k个节点 #5、接下来,两个指针同时向后移动,直到former来到了最后一个节点位置 whileformer.next: #former不断向后移动 former=former.next #latter不断向后移动 latter=latter.next #6、此时,former指向了最后一个节点,需要将这个节点和原链表的头节点连接起来 former.next=head #7、latter指向的节点的【下一个节点】是倒数第k个节点,那就是旋转成功之后的头节点 newHead=latter.next #8、断开链接,避免成环 latter.next=None #9、返回newHead returnnewHead
四、复杂度分析
时间复杂度:链表一共被遍历两次,因此总的时间复杂度为O(n),n是链表的长度。
空间复杂度:O(1),我们只需要常数的空间存储若干变量。
审核编辑:刘清
-
JAVA
+关注
关注
20文章
2997浏览量
115685
原文标题:旋转链表(LeetCode 61)
文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
C语言-链表(单向链表、双向链表)
C语言单向链表
玩转C语言链表-链表各类操作详解
数据结构链表的基本操作
OpenHarmony中的HDF单链表及其迭代器
OpenHarmony中的HDF单链表及其迭代器
C语言基础教程之链表
驱动之路-内核链表的使用
双向循环链表的创建
链表的基础知识

移动旋转链表的每个节点
评论