寻找两个有序数组的中位数与正则表达式匹配

在算法学习和面试中,有序数组中位数查找、正则表达式匹配是两类极具代表性的问题,分别考察了二分查找的灵活运用和动态规划的状态转移思想。本文将详细解析这两个问题的解题思路,并结合代码实现深入剖析核心逻辑。

一、寻找两个有序数组的中位数

问题背景

给定两个大小分别为 m 和 n 的有序数组 nums1 和 nums2,要求找出并返回这两个有序数组的中位数,且算法的时间复杂度需达到 O(log(m+n))

核心思路:二分查找分割线

中位数的本质是将有序集合划分为左右两部分,且左右部分元素数量相等(或差值不超过 1),左半部分最大值小于等于右半部分最小值。基于此,我们可以通过二分查找确定分割线位置:

二、正则表达式匹配

问题背景

给定字符串 s 和模式 p,实现支持 . 和 * 的正则表达式匹配:

核心思路:动态规划

定义二维数组 f[i][j] 表示 s 的前 i 个字符与 p 的前 j 个字符是否匹配,通过状态转移逐步推导:

代码实现与解析

  1. 简化问题:始终让 nums1 为较短数组,减少二分查找的次数;
  2. 分割规则:设 nums1 分割点为 inums2 分割点为 j,需满足 i + j = (m + n + 1) / 2(保证左半部分元素数量≥右半部分);
  3. 边界处理:分割点在数组首尾时,用 INT_MIN/INT_MAX 表示空区间的极值;
  4. 调整分割线:若 nums1[i-1] > nums2[j],说明分割线需左移;若 nums1[i-1] ≤ nums2[j],说明分割线可右移,同时记录左半部分最大值和右半部分最小值。

    关键细节

  5. 时间复杂度:O(log(min(m,n))),因为始终对较短数组二分;
  6. 边界值 INT_MIN/INT_MAX 避免了额外的条件判断,简化了逻辑;
  7. 分割线公式 j = (m + n + 1) / 2 - i 保证了奇偶长度下,左半部分元素数量都不小于右半部分。
  8. . 匹配任意单个字符;
  9. * 匹配零个或多个前面的那一个元素。要求匹配整个字符串 s,而非部分匹配。
  10. 基础状态f[0][0] = true(空字符串匹配空模式);
  11. 处理 *
    • 匹配零个:f[i][j] = f[i][j-2](忽略 * 和其前一个字符);
    • 匹配多个:若 s[i-1] 与 p[j-2] 匹配,则 f[i][j] = f[i-1][j](复用 * 匹配前一个字符);
  12. 处理普通字符 /.:若 s[i-1] 与 p[j-1] 匹配,则 f[i][j] = f[i-1][j-1]

关键细节

辅助函数 matches 统一处理字符匹配逻辑,简化代码; 动态规划数组维度为 (m+1)x(n+1),包含空字符串的情况;

三、总结

  1. 寻找中位数:核心是利用二分查找确定分割线,通过控制分割线位置保证左右部分的平衡性,时间复杂度优化至对数级别,关键在于边界处理和分割线公式的推导;
  2. 正则匹配:动态规划是解决这类匹配问题的经典方法,核心是定义清晰的状态转移方程,重点处理 * 的零次 / 多次匹配逻辑;
  3. 两类问题分别体现了 “分治二分” 和 “动态规划” 的核心思想,前者通过缩小问题规模提高效率,后者通过状态转移逐步推导结果,都是算法学习中必须掌握的核心思路。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值