21.合并两个有序链表(简单)一文搞懂单链表的六大解题套路 :: labuladong的算法小抄
21.合并两个有序链表(简单)
思路:
常规解法,两两比较
思路:优先级队列主要方法——插入和删除(两个方法都自带重排序功能)
合并 k
个有序链表的逻辑类似合并两个有序链表,难点在于,如何快速得到 k
个节点中的最小节点,接到结果链表上?
这里我们就要用到 优先级队列(二叉堆) 这种数据结构,把链表节点放入一个最小堆,就可以每次获得 k
个节点中的最小节点;
思路:快慢指针
快指针是慢指针的速度的两倍,快指针走完了,慢指针的位置就是中间点(如果链表长度是偶数,则命中后面的节点)
思路:双指针
两个指针(速度相同),第一个指针先出发k步,然后第二个指针开始出发,和第一个指针同步前进,第一个指针到达终点,此时第二个指针的位置就是我们要的
思路:快慢指针相遇
142.环形链表 II(中等)找出链表的环起点
思路:快慢指针前期辅助,双指针相遇 通过选定合理的时机和地点,制造两指针距离目标点相同,于是两指针相遇
160.相交链表(简单)返回相交链表节点
思路:制造环,双指针相遇
通过选定合理的时机和地点,制造两指针距离目标点相同,于是两指针相遇
思路:递归
ListNode reverse(ListNode head)
{
if (head.next == null) return head;
ListNode last = reverse(head.next);
head.next.next = head; head.next = null;
return last;
}
升级版本:反转链表的前N个节点
思路:递归
/** * 进阶:反转链表前N个节点,并返回反转后的头节点--递归反转 */ ListNode reversen(ListNode head, int n) { //递归的停止条件 if (1 == n) return head; //递归方法 ListNode last = reversen(head.next, n - 1); //方法里的动作 ListNode otherhead = head.next.next; head.next.next = head; head.next = otherhead; return last; }
验证:
@Test public void reversenTest() { ListNode head = new ListNode(1); ListNode node2 = new ListNode(2); ListNode node3 = new ListNode(3); ListNode node4 = new ListNode(4); ListNode node5 = new ListNode(5); ListNode node6 = new ListNode(6); ListNode node7 = new ListNode(7); ListNode node8 = new ListNode(8); node7.next = node8; node6.next = node7; node5.next = node6; node4.next = node5; node3.next = node4; node2.next = node3; head.next = node2; ListNode p = head; while (null != p.next) { Integer pval = p.val; logger.info(pval.toString()); p = p.next; } ListNode last = reversen(head, 5); p = last; while (null != p.next) { Integer pval = p.val; logger.info(pval.toString()); p = p.next; } }
升级版本:反转链表的前(M,N)个节点
思路:递归
ListNode reverseBetween(ListNode head, int m, int n) { // base case if (m == 1) { return reverseN(head, n); } // 前进到反转的起点触发 base case head.next = reverseBetween(head.next, m - 1, n - 1); return head; }
总结:
递归的思想相对迭代思想,稍微有点难以理解,处理的技巧是:不要跳进递归,而是利用明确的定义来实现算法逻辑。
处理看起来比较困难的问题,可以尝试化整为零,把一些简单的解法进行修改,解决困难的问题。
值得一提的是,递归操作链表并不高效。和迭代解法相比,虽然时间复杂度都是 O(N),但是迭代解法的空间复杂度是 O(1),而递归解法需要堆栈,空间复杂度是 O(N)。所以递归操作链表可以作为对递归算法的练习或者拿去和小伙伴装逼,但是考虑效率的话还是使用迭代算法更好。
思想:寻找回文串(或回文序列)的核心思想是从中心向两端扩展