面试算法|23. Merge k Sorted Lists的三种解法

本文详细介绍了如何解决合并k个已排序链表的问题,包括暴力解法、使用优先队列和分治法。暴力解法由于比较次数过多效率低下,优先队列法在初始化和弹出操作上进行了优化,而分治法则通过不断合并两两已排序链表达到时间复杂度为Nlogk的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

23. Merge k Sorted Lists

一道非常经典的题目。第二次做,学着用三种方法来解答,并且不断优化

解法1 暴力

每次都对 K K K个list进行循环,找到最小的那个Node加入我们最后的结果list。
time complexity: O ( k N ) O(kN) O(kN)
N N N个数字,每个数字都要经过k次比较才会放进结果list中,不可取。

在Java面试中,算法题是常见的考察点之一。下面我将列举几个经典的Java算法题,并给出详细的解答和实现代码。 --- ### 1. **两数之和(Two Sum)** **题目描述:** 给定一个整数数组 `nums` 和一个目标值 `target`,请你在该数组中找出和为目标值的那两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两次。 **示例:** ``` 输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] = 9,所以返回 [0, 1] ``` **解法:使用哈希表记录已遍历元素** ```java import java.util.HashMap; public class TwoSum { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } throw new IllegalArgumentException("No two sum solution"); } } ``` **解释:** - 我们使用一个哈希表来存储已经遍历过的数字及其索引。 - 每次遍历时,计算当前数字与目标值的差值 `complement`。 - 如果这个差值存在于哈希表中,则说明我们找到了对应的两个数,直接返回它们的索引。 - 否则将当前数字存入哈希表,继续下一次循环。 --- ### 2. **反转链表(Reverse Linked List)** **题目描述:** 反转一个单链表。 **示例:** ``` 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL ``` **解法:迭代方式反转链表** ```java class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public class ReverseLinkedList { public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } } ``` **解释:** - 使用三个指针:`prev` 表示前一个节点,`curr` 当前节点,`nextTemp` 临时保存下一个节点。 - 在每次循环中: - 先保存当前节点的下一个节点; - 然后将当前节点的 `next` 指向前一个节点; - 更新 `prev` 和 `curr` 继续向后移动。 - 最终 `prev` 成为新的头节点。 --- ### 3. **最长回文子串(Longest Palindromic Substring)** **题目描述:** 给定一个字符串 `s`,找到 `s` 中最长的回文子串。 **示例:** ``` 输入: "babad" 输出: "bab" 或 "aba" 都是有效答案 ``` **解法:中心扩展法** ```java public class LongestPalindrome { private int start = 0; private int maxLen = 0; public String longestPalindrome(String s) { if (s == null || s.length() < 2) return s; for (int i = 0; i < s.length(); i++) { expandAroundCenter(s, i, i); // 奇数长度 expandAroundCenter(s, i, i + 1); // 偶数长度 } return s.substring(start, start + maxLen); } private void expandAroundCenter(String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { left--; right++; } // 回到有效的边界 left++; right--; if (right - left + 1 > maxLen) { start = left; maxLen = right - left + 1; } } } ``` **解释:** - 对于每个字符,尝试以它为中心向两边扩展,判断是否是回文。 - 分别处理奇数长度(中心是一个字符)和偶数长度(中心是两个字符)的情况。 - 记录最长回文子串的起始位置和长度。 --- ### 4. **合并两个有序链表(Merge Two Sorted Lists)** **题目描述:** 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 **示例:** ``` 输入:l1 = 1->2->4, l2 = 1->3->4 输出:1->1->2->3->4->4 ``` **解法:递归或迭代方法** ```java class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public class MergeTwoLists { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; if (l1.val < l2.val) { l1.next = mergeTwoLists(l1.next, l2); return l1; } else { l2.next = mergeTwoLists(l1, l2.next); return l2; } } } ``` **解释:** - 使用递归的方式比较两个链表的当前节点值,选择较小的那个作为当前节点,并递归地合并剩下的部分。 - 这是一种简洁高效的写法,但要注意递归深度限制问题。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值