每日算法(第十八期)

先来回顾一下上期的问题及答案:

2023年6月7日

「正则表达式匹配」(Regular Expression Matching)。 以下是题目的描述: 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

  • '.' 匹配任意单个字符。

  • '*' 匹配零个或多个前面的那一个元素。

所谓匹配,是要涵盖整个字符串 s 的,而不是部分字符串。

以下是对应的JavaScript解答:

function isMatch(s, p) {
  const m = s.length;
  const n = p.length;

  const dp = new Array(m + 1);
  for (let i = 0; i < dp.length; i++) {
    dp[i] = new Array(n + 1).fill(false);
  }

  dp[0][0] = true;
  for (let j = 1; j <= n; j++) {
    if (p[j - 1] === '*') {
      dp[0][j] = dp[0][j - 2];
    }
  }

  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (p[j - 1] === '.' || p[j - 1] === s[i - 1]) {
        dp[i][j] = dp[i - 1][j - 1];
      } else if (p[j - 1] === '*') {
        if (p[j - 2] === '.' || p[j - 2] === s[i - 1]) {
          dp[i][j] = dp[i][j - 2] || dp[i - 1][j];
        } else {
          dp[i][j] = dp[i][j - 2];
        }
      }
    }
  }

  return dp[m][n];
}

解题思路:

  • 使用动态规划的思想解决问题。

  • 定义二维数组 dp,其中 dp[i][j] 表示字符串 s 的前 i 个字符和模式 p 的前 j 个字符是否匹配。

  • 初始化 dp[0][0]true,表示空字符串和空模式匹配。

  • 遍历字符串 p,初始化第一行 dp[0][j]。如果当前字符为 '*',则将 dp[0][j] 设置为 dp[0][j - 2],表示当前模式匹配零次。

  • 遍历字符串 s 和模式 p,根据字符匹配情况更新 dp 数组。

  • 如果当前字符匹配或模式为 .,则当前状态由 dp[i - 1][j - 1] 决定。

  • 如果当前模式为 '*',则需要考虑两种情况:1)当前字符和模式的前一个字符匹配,即 p[j - 2] === '.'p[j - 2] === s[i - 1],则当前状态由 dp[i][j - 2](匹配零次)

dp[i - 1][j](匹配多次)决定;2)当前字符和模式的前一个字符不匹配,即 p[j - 2] !== s[i - 1],则当前状态由 dp[i][j - 2](匹配零次)决定。

时间复杂度分析:

  • 动态规划解法中,需要遍历整个字符串 s 和模式 p,时间复杂度为 O(m * n),其中 m 和 n 分别为字符串 s 和模式 p 的长度。

空间复杂度分析:

  • 使用了一个二维数组 dp 来存储中间状态,空间复杂度为 O(m * n)。

注意:这道题还可以使用递归的方式进行解答,但动态规划解法更为高效。

2023年6月8日

「整数转罗马数字」(Integer to Roman)。以下是题目的描述:

罗马数字包含以下七种字符:I,V,X,L,C,D 和 M。

字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000

例如,罗马数字2写做 II ,即为两个并列的1。12写做 XII ,即为 X+II 。27 写做 XXVII, 即为 XX+V+II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

上面问题的答案会在第二天的公众号推文中公布,大家可以关注公众号:程序员每日三问,第一时间获得推送内容。

学习不打烊,充电加油只为遇到更好的自己,每天早上9点纯手工发布面试题(死磕自己,愉悦大家) 希望大家在这浮夸的程序员圈里保持冷静,每天坚持花20分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。

你可能感兴趣的:(算法)