290.单词规律

/**
 * @param {string} pattern
 * @param {string} s
 * @return {boolean}
 */
var wordPattern = function (pattern, s) {
    let wordArr = s.split(' ')
    // console.log(wordArr)
    if (wordArr.length !== pattern.length) {
        return false
    }

    // 先记录pattern每个字母出现的下标
    let map = {}
    for (let i = 0; i < pattern.length; i++) {
        let char = pattern.charAt(i)
        if (map[char]) {
            map[char].push(i)
        } else {
            map[char] = [i]
        }
    }
    // console.log(map)

    // 看对应map下标的单词是否都相同,另外还要记录被检查过的单词
    let checkedWords = [] // 为啥要用数组,如果有个单词为'constructor'的话,你可以看看map['constructor']是啥东西
    let indexesArr = Object.values(map)
    for (let i = 0; i < indexesArr.length; i++) {
        let indexes = indexesArr[i]
        let curWord = wordArr[indexes[0]] // 要检查的单词
        // console.log(curWord)
        // 已经检查过的单词后面还出现了,说明次数对不上
        if (checkedWords.includes(curWord)) {
            return false
        }
        for (let j = 1; j < indexes.length; j++) {
            if (wordArr[indexes[j]] !== curWord) {
                return false
            }
        }
        // 记录检查过的单词
        checkedWords.push(curWord)
    }

    return true
};

// 只需要一次遍历
var wordPattern = function (pattern, s) {
    // 设定每个单词对应的哪个字符
    let word2char = new Map() // 尽量使用Map构造函数,否则let map={},如果key=‘constructor’会有问题
    let char2word = new Map()

    let words = s.split(' ')
    if (words.length !== pattern.length) {
        return false
    }

    for (let i = 0; i < words.length; i++) {
        // 假设第一个单词对应第一个字符
        let word = words[i]
        let char = pattern.charAt(i)
        if (word2char.has(word) && word2char.get(word) !== char) {
            return false
        }
        if (char2word.has(char) && char2word.get(char) !== word) {
            return false
        }

        word2char.set(word, char)
        char2word.set(char, word)
    }

    return true
}

console.log(wordPattern("abba", "dog constructor constructor dog"))