前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【一天一大 lee】单词规律 II (难度:困难) - Day20201217

【一天一大 lee】单词规律 II (难度:困难) - Day20201217

作者头像
前端小书童
发布2021-01-05 10:08:25
3830
发布2021-01-05 10:08:25
举报
文章被收录于专栏:前端小书童前端小书童

more-035

题目:

给你一种规律 pattern 和一个字符串 str,请你判断 str 是否遵循其相同的规律。

这里我们指的是 完全遵循,例如 pattern 里的每个字母和字符串 str 中每个 非空 单词之间,存在着 双射 的对应规律。双射 意味着映射双方一一对应,不会存在两个字符映射到同一个字符串,也不会存在一个字符分别映射到两个不同的字符串。

示例:

  1. 示例 1:
代码语言:javascript
复制
输入:pattern = "abab", s = "redblueredblue"
输出:true
解释:一种可能的映射如下:
'a' -> "red"
'b' -> "blue"
  1. 示例 2:
代码语言:javascript
复制
输入:pattern = "aaaa", s = "asdasdasdasd"
输出:true
解释:一种可能的映射如下:
'a' -> "asd"
  1. 示例 3:
代码语言:javascript
复制
输入:pattern = "abab", s = "asdasdasdasd"
输出:true
解释:一种可能的映射如下:
'a' -> "a"
'b' -> "sdasd"
注意 'a' 和 'b' 不能同时映射到 "asd",因为这里的映射是一种双射。
  1. 示例 4:
代码语言:javascript
复制
输入:pattern = "aabb", s = "xyzabcxzyabc"
输出:false

提示:

  • 0 <= pattern.length <= 20
  • 0 <= s.length <= 50
  • pattern 和 s 由小写英文字母组成

抛砖引玉

相对于20201216:单词规律 (难度:简单)本题失去了 s 中确定分割的单个元素,但是基于前面的逻辑:

  • 声明两个 map 作为哈希表,来表达两个字符双向的映射关系
  • 遇到映射关系冲突返回 false
代码语言:javascript
复制
pMs : pItem -> mapStr === sItem
sMp : sItem -> mapPat === pItem

其中 pItem 是单个模式字符,sItem 是从 s 中分割的字符串片段

那么逐个从 p 中取出元素(pItem)在 s 中尝试各种匹配组合:

  • 如果 pItem 之前已经存在了映射字符串片段 sItem,那么校验枚举的字符片段是否与映射关系一致, 如果之前的映射关系不一致,说明本轮枚举的 sItem 一定不满足继续枚举,如果满足,则递归匹配后续 pattern、s
  • 如果 pItem 不存在映射字符串片段则在 pMs、sMp 分别添加映射关系

抛砖引玉

代码语言:javascript
复制
/**
 * @param {string} pattern
 * @param {string} s
 * @return {boolean}
 */
var wordPatternMatch = function(pattern, s) {
    let pMs = new Map(),
        sMp = new Map()
    function helper(str, index, pMs, sMp) {
        // 当p中元素取完且s也分割完则说明匹配成功
        if (index >= pattern.length) {
            if (str) return false
            return true
        }
        const pItem = pattern[index],
            mapStr = pMs.get(pItem)
        for (let i = 1; i <= str.length; i++) {
            const sItem = str.substring(0, i),
                mapPat = sMp.get(sItem)
            // s分割的片段不满足之前的映射关系,直接继续枚举sItem
            if (
                (pMs.has(pItem) && mapPat !== pItem) ||
                (sMp.has(sItem) && mapStr !== sItem)
            ) {
                continue
            }
            // 如果不存在p元素的映射则新增映射关系
            if (!pMs.has(pItem)) {
                pMs.set(pItem, sItem)
                sMp.set(sItem, pItem)
            }
            // 递归后续匹配
            if (helper(str.slice(i), index + 1, pMs, sMp)) return true
            // 如果本轮枚举s片段时pItem映射的s片段为空,那么在每次枚举前都需要把映射关系重置回去
            if (!mapStr) {
                pMs.delete(pItem)
                sMp.delete(sItem)
            }
        }
        return false
    }
    // 特殊情况:都为空或者只有个为空
    if (!pattern && !s) return true
    if (!pattern || !s) return false
    return helper(s, 0, pMs, sMp)
}

从上面解法可以看出来,本题的出题逻辑是从 pattern 中逐个选择元素然后分割 s 字符片段去尝试匹配,两个哈希表记录模式串与匹配串的映射关系

单从空间复杂度上看,其实每次校验是否冲突也是可以通过再次遍历哈希表完成:

  • 从 pattern 中逐个截取元素与 s 片段匹配
  • 如果之前哈希中存在本轮 pattern 选取的元素则交易是否相同(不相同继续枚举 s 片段,相同则切割 pattern 和 s 继续匹配剩余部分),如果不存在则新增映射
代码语言:javascript
复制
var wordPatternMatch = function(pattern, s) {
    let map = new Map()
    function helper(pStr, sStr) {
        // 匹配完成
        if (pStr.length === 0) return sStr.length === 0
        const pItem = pStr[0],
            mapStr = map.get(pItem)
        // 枚举s片段组合:pattern和s均切割则枚举时s边界发生变化
        for (let i = 1; i <= sStr.length - pStr.length + 1; i++) {
            const sItem = sStr.substring(0, i)
            // 遇到已匹配映射或者找到全新映射
            if (
                (mapStr && sItem == mapStr) ||
                (!mapStr && ![...map.values()].includes(sItem))
            ) {
                map.set(pItem, sItem)
                if (helper(pStr.substring(1), sStr.substring(i), map)) {
                    return true
                } else if (!mapStr) {
                    map.delete(pItem)
                }
            }
        }
        return false
    }
    return helper(pattern, s)
}

博客: 前端小书童

每天的每日一题,写的题解会同步更新到公众号一天一大 lee 栏目 欢迎关注留言

公众号:前端小书童

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端小书童 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目:
    • 示例:
    • 抛砖引玉
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档