一、题目描述
给你一个链表的头节点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
+关注
关注
19文章
2978浏览量
105443
原文标题:旋转链表(LeetCode 61)
文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
C语言-链表(单向链表、双向链表)
C语言单向链表
玩转C语言链表-链表各类操作详解
数据结构链表的基本操作
OpenHarmony中的HDF单链表及其迭代器
OpenHarmony中的HDF单链表及其迭代器
C语言基础教程之链表
驱动之路-内核链表的使用

双向循环链表的创建
链表的基础知识

评论