在算法学习和面试中,有序数组中位数查找、正则表达式匹配是两类极具代表性的问题,分别考察了二分查找的灵活运用和动态规划的状态转移思想。本文将详细解析这两个问题的解题思路,并结合代码实现深入剖析核心逻辑。
一、寻找两个有序数组的中位数
问题背景
给定两个大小分别为 m 和 n 的有序数组 nums1 和 nums2,要求找出并返回这两个有序数组的中位数,且算法的时间复杂度需达到 O(log(m+n))。
核心思路:二分查找分割线
中位数的本质是将有序集合划分为左右两部分,且左右部分元素数量相等(或差值不超过 1),左半部分最大值小于等于右半部分最小值。基于此,我们可以通过二分查找确定分割线位置:
二、正则表达式匹配
问题背景
给定字符串 s 和模式 p,实现支持 . 和 * 的正则表达式匹配:
核心思路:动态规划
定义二维数组 f[i][j] 表示 s 的前 i 个字符与 p 的前 j 个字符是否匹配,通过状态转移逐步推导:
代码实现与解析
- 简化问题:始终让
nums1为较短数组,减少二分查找的次数; - 分割规则:设
nums1分割点为i,nums2分割点为j,需满足i + j = (m + n + 1) / 2(保证左半部分元素数量≥右半部分); - 边界处理:分割点在数组首尾时,用
INT_MIN/INT_MAX表示空区间的极值; - 调整分割线:若
nums1[i-1] > nums2[j],说明分割线需左移;若nums1[i-1] ≤ nums2[j],说明分割线可右移,同时记录左半部分最大值和右半部分最小值。关键细节
- 时间复杂度:
O(log(min(m,n))),因为始终对较短数组二分; - 边界值
INT_MIN/INT_MAX避免了额外的条件判断,简化了逻辑; - 分割线公式
j = (m + n + 1) / 2 - i保证了奇偶长度下,左半部分元素数量都不小于右半部分。 .匹配任意单个字符;*匹配零个或多个前面的那一个元素。要求匹配整个字符串s,而非部分匹配。- 基础状态:
f[0][0] = true(空字符串匹配空模式); - 处理
*:- 匹配零个:
f[i][j] = f[i][j-2](忽略*和其前一个字符); - 匹配多个:若
s[i-1]与p[j-2]匹配,则f[i][j] = f[i-1][j](复用*匹配前一个字符);
- 匹配零个:
- 处理普通字符 /
.:若s[i-1]与p[j-1]匹配,则f[i][j] = f[i-1][j-1]。
关键细节
辅助函数 matches 统一处理字符匹配逻辑,简化代码; 动态规划数组维度为 (m+1)x(n+1),包含空字符串的情况;
三、总结
- 寻找中位数:核心是利用二分查找确定分割线,通过控制分割线位置保证左右部分的平衡性,时间复杂度优化至对数级别,关键在于边界处理和分割线公式的推导;
- 正则匹配:动态规划是解决这类匹配问题的经典方法,核心是定义清晰的状态转移方程,重点处理
*的零次 / 多次匹配逻辑; - 两类问题分别体现了 “分治二分” 和 “动态规划” 的核心思想,前者通过缩小问题规模提高效率,后者通过状态转移逐步推导结果,都是算法学习中必须掌握的核心思路。
1963

被折叠的 条评论
为什么被折叠?



