这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战
前言
力扣第六十一题 旋转链表
如下所示:
给你一个链表的头节点 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]
一、思路
这一题题目意思比较容易理解:就是将链表尾部 k
个元素放置到链表的头部中
我一开始使用快慢指针写的,但是不太好处理 k > head.len
的情况。例如示例2中的 head = [0,1,2], k = 4
就是 k > head.len
。
所以我就换了一种思路,实现的步骤大致分为以下两个步骤:
- 将链表的尾部指向头部形成圆环,此时临时指针
headTemp
指向链表尾部 - 再找到圆环断开的位置
- 返回新的头节点
newHead
图解算法
此处以 head = [1, 2, 3, 4, 5], k = 12
作为例子
- 先将尾部指向头部形成圆环
- 找到圆环断开的位置
我们知道临时指针 headTemp
在形成圆环时指向链表的最后一个节点,即 5
我们知道当 k = 1
时,圆环应该在 4 -> 5
断开,此时从临时指针开始需要走的步数为 p = 4
,如下图所示:
当 k = 2
的时候,圆环应该在 3 -> 4
断开,此时从临时指针开始需要走的步数为 p = 3
,如下图所示:
我们发现断开的位置是从后往前的,当 k == head.len
,即 k == 5
时,相当于发生了一次循环。圆环应该在链表的尾节点指向头节点的地方断开,即 5 -> 1
的地方。如下图所示:
综上所述,断开的位置为:从临时指针 headTemp
开始,走 p = len - k % len
步即可断开(为了走最少的步数,所以进行了取余)
所以 k = 12
断开的位置为从临时指针走 p = 5 - 12%5 = 3
步断开,如下图所示:
二、实现
实现代码
实现代码与思路中保持一致,值得注意的是当 head == null
时直接返回结果 null
即可。
/**
* 链表转圆环
*/
public ListNode rotateRight(ListNode head, int k) {
// 特殊情况
if (head == null) {
return null;
}
// 先把它变成一个圆
int len = 0;
ListNode headTemp = head;
while (true) {
len++;
if (headTemp.next == null) {
headTemp.next = head;
break;
}
headTemp = headTemp.next;
}
// 看在哪里断开
int p = len - k % len;
while (p > 0) {
headTemp = headTemp.next;
p--;
}
ListNode newHead = headTemp.next;
headTemp.next = null;
return newHead;
}
测试代码
public static void main(String[] args) {
ListNode listNode = new ListNode(1, new ListNode(2, new ListNode
(3, new ListNode(4, new ListNode(5)))));
new Number61().rotateRight(listNode, 12);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~