网站首页 > 精选教程 正文
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
解法1
一开始可以发现,有如下三种特殊情况是可以直接不进行任何处理,直接返回head的:
- head为null,整个链表都是null
- head的next为空,代表链表只有一个元素,此时不论右移多少次,都是本身
- k=0
考虑k的取值, 如果k的值正好是链表长度的整数倍,这种情况右移后还是原链表本身。返回即可。
接下来,如果k远远超过链表的长度,我们也没必要进行过多的右移,获取k对链表长度的余数即为右移的次数。
一个难点在于,在单向链表中找到一个元素的父亲节点的时间复杂度很高。此时第一个想法是翻转链表、新链表左移、再次翻转链表。
也写出了第一版代码。
代码1
java实现
class Solution { public ListNode rotateRight(ListNode head, int k) { //三种情况,链表为空、链表只有一个元素、移动位置为0 if (head == null ||head.next == null || k == 0) { return head; } ListNode tail = head; ListNode temp = head; //判断长度 int i = 1; while (temp.next != null) { temp = temp.next; i++; } k = k % i; //当旋转整数倍时,没有必要挪动数据,直接返回head if (k == 0) { return head; } //翻转链表 head = reverse(head); while(k>0) { tail.next = head; tail = head; head = head.next; tail.next = null; k--; } head = reverse(head); return head; } //翻转链表 ListNode reverse (ListNode head) { ListNode prev = head; ListNode curr = head.next; while (curr!=null) { ListNode temp = curr.next; curr.next = prev; prev = curr; curr = temp; } head.next = null; return prev; } }
解法2
解法1的问题在于有两次翻转链表,虽然只是O(n)
的时间复杂度,但是本着能少一步是一步的原则,还是能省则省。
继续观察示例1,发现,右移2
位,实际上是左移3
位,而左移是解法1里就实现了的。这就不需要翻转链表就可以直接移动了。
代码2
java实现
class Solution { public ListNode rotateRight(ListNode head, int k) { //三种情况,链表为空、链表只有一个元素、移动位置为0 if (head == null ||head.next == null || k == 0) { return head; } ListNode tail = head; ListNode temp = head; //判断长度 int i = 1; while (tail.next != null) { temp = tail; tail = tail.next; i++; } k = k % i; //当旋转整数倍时,没有必要挪动数据,直接返回head if (k == 0) { return head; } //增加了一步k的计算 k = i-k; //翻转链表 //注释掉解法1的翻转链表 //head = reverse(head); while(k>0) { tail.next = head; tail = head; head = head.next; tail.next = null; k--; } //注释掉解法1的翻转链表 //head = reverse(head); return head; } //翻转链表 ListNode reverse (ListNode head) { ListNode prev = head; ListNode curr = head.next; while (curr!=null) { ListNode temp = curr.next; curr.next = prev; prev = curr; curr = temp; } head.next = null; return prev; } }
仔细观察代码,实际上是去掉了翻转链表,对k进行了更进一步的操作而已。相比解法一,代码更加的清晰。
猜你喜欢
- 2024-11-02 LeetCode-025-K 个一组翻转链表 每k个一组翻转链表
- 2024-11-02 C++算法(五)反转链表 反转链表c#
- 2024-11-02 字节面试算法集第三题链表反转 #算法
- 2024-11-02 Java数据结构和算法—链表 java中的链表数据结构
- 2024-11-02 面试现场:如何实现链表的逆序? 链表逆置是什么意思
- 2024-11-02 LeetCode-206-反转链表 反转链表 迭代
- 2024-11-02 迭代法 链表翻转 #软件开发 迭代法程序
- 2024-11-02 每日算法---单链表反转和是否有环
- 2024-11-02 C++:挑战鹅厂面试题(一)--反转链表
- 2024-11-02 极客算法训练笔记(三),链表详细图解,别再逃避了朋友
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)