[10] 正则表达式匹配
1.[6] N 字形变换2.[7] 整数反转3.[5] 最长回文子串4.[4] 寻找两个正序数组的中位数5.[3] 无重复字符的最长子串6.[2] 两数相加7.[1] 两数之和8.[8] 字符串转换整数 (atoi)9.[9] 回文数
10.[10] 正则表达式匹配
11.[11] 盛最多水的容器12.[12] 整数转罗马数字13.[13] 罗马数字转整数14.[14] 最长公共前缀15.[15] 三数之和16.[16] 最接近的三数之和17.[17] 电话号码的字母组合18.[18] 四数之和19.[19] 删除链表的倒数第 N 个结点20.[20] 有效的括号21.[21] 合并两个有序链表22.[22] 括号生成23.[23] 合并 K 个升序链表24.[24] 两两交换链表中的节点25.[25] K 个一组翻转链表26.[26] 删除有序数组中的重复项27.[27] 移除元素28.[28] 找出字符串中第一个匹配项的下标29.[29] 两数相除30.[30] 串联所有单词的子串31.[31] 下一个排列32.[32] 最长有效括号33.[33] 搜索旋转排序数组34.[34] 在排序数组中查找元素的第一个和最后一个位置35.[35] 搜索插入位置36.[36] 有效的数独37.[37] 解数独38.[38] 外观数列39.[39] 组合总和40.[40] 组合总和 II41.[41] 缺失的第一个正数42.[42] 接雨水43.[43] 字符串相乘44.[44] 通配符匹配45.[45] 跳跃游戏 II46.[46] 全排列47.[47] 全排列 II48.[48] 旋转图像49.[49] 字母异位词分组50.[50] Pow(x, n)51.[51] N 皇后52.[52] N 皇后 II53.[53] 最大子数组和54.[54] 螺旋矩阵55.[55] 跳跃游戏56.[56] 合并区间57.[57] 插入区间58.[58] 最后一个单词的长度59.[59] 螺旋矩阵 II60.[60] 排列序列61.[61] 旋转链表62.[62] 不同路径63.[63] 不同路径 II64.[64] 最小路径和65.[65] 有效数字66.[66] 加一67.[67] 二进制求和68.[68] 文本左右对齐69.[69] x 的平方根70.[70] 爬楼梯71.[71] 简化路径72.[72] 编辑距离73.[73] 矩阵置零74.[74] 搜索二维矩阵75.[75] 颜色分类76.[76] 最小覆盖子串77.[77] 组合78.[78] 子集79.[79] 单词搜索80.[80] 删除有序数组中的重复项 II/** * @param {string} s * @param {string} p * @return {boolean} */ var isMatch = function (s, p) { if (s == null || p == null) return false;//极端情况 s和p都是空 返回false const sLen = s.length, pLen = p.length; const dp = new Array(sLen + 1);//因为位置是从0开始的,第0个位置是空字符串 所以初始化长度是sLen + 1 for (let i = 0; i < dp.length; i++) {//初始化dp数组 dp[i] = new Array(pLen + 1).fill(false); // 将项默认为false } // base case s和p第0个位置是匹配的 dp[0][0] = true; for (let j = 1; j < pLen + 1; j++) {//初始化dp的第一列,此时s的位置是0 //情况1:如果p的第j-1个位置是*,则j的状态等于j-2的状态 //例如:s='' p='a*' 相当于p向前看2个位置如果匹配,则*相当于重复0个字符 if (p[j - 1] == "*") dp[0][j] = dp[0][j - 2]; } // 迭代 for (let i = 1; i < sLen + 1; i++) { for (let j = 1; j < pLen + 1; j++) { //情况2:如果s和p当前字符是相等的 或者p当前位置是. 则当前的dp[i][j] 可由dp[i - 1][j - 1]转移过来 //当前位置相匹配,则s和p都向前看一位 如果前面所有字符相匹配 则当前位置前面的所有字符也匹配 //例如:s='XXXa' p='XXX.' 或者 s='XXXa' p='XXXa' if (s[i - 1] == p[j - 1] || p[j - 1] == ".") { dp[i][j] = dp[i - 1][j - 1]; } else if (p[j - 1] == "*") {//情况3:进入当前字符不匹配的分支 如果当前p是* 则有可能会匹配 //s当前位置和p前一个位置相同 或者p前一个位置等于. 则有三种可能 //其中一种情况能匹配 则当前位置的状态也能匹配 //dp[i][j - 2]:p向前看2个位置,相当于*重复了0次, //dp[i][j - 1]:p向前看1个位置,相当于*重复了1次 //dp[i - 1][j]:s向前看一个位置,相当于*重复了n次 //例如 s='XXXa' p='XXXa*' if (s[i - 1] == p[j - 2] || p[j - 2] == ".") { dp[i][j] = dp[i][j - 2] || dp[i][j - 1] || dp[i - 1][j]; } else { //情况4:s当前位置和p前2个位置不匹配,则相当于*重复了0次 //例如 s='XXXb' p='XXXa*' 当前位置的状态和p向前看2个位置的状态相同 dp[i][j] = dp[i][j - 2]; } } } } return dp[sLen][pLen]; // 长为sLen的s串 是否匹配 长为pLen的p串 };