leetcode每日一题(2020-07-27)392. 判断子序列

题目描述:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

后续挑战 :
如果有大量输入的 S,称作S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

今日学习:
1.ASCII码与字符串转换:'a'.charCodeAt() = 97; String.fromCharCode(97) = 'a'
2.动规真的好灵活,奇奇怪怪
3.昨天的:判断越界可以先写出全部坐标再加限制条件筛选,不用先考虑什么样的限制条件下会出现什么样的坐标

题解:
1.瞎琢磨的,但其实不用每次都slice s,可以for遍历s
2.常规双指针
3.奇怪动规

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
// 相当于暴力法,而且改变了s和t,很垃圾
var isSubsequence = function(s, t) {
    if(s.length == 0) return true
    if(t.length == 0) return false
    while(s.length > 0 && t.length > 0) {
        let cur = s[0]
        let index = t.indexOf(cur)
        if(index != -1) {
            s = s.slice(1)
            t = t.slice(index + 1)
        }else {
            return false
        }
    }
    if(s.length == 0) return true
    else return false
};
// 双指针,比我的暴力法好很多
var isSubsequence = function(s, t) {
    let n = s.length, m = t.length
    if(n == 0) return true
    if(m == 0) return false
    let i = j = 0
    while(i < n && j < m) {
        if(s[i] == t[j]) {
            i++
        }
        j++
    }
    return i == n
}
// 我没想到居然还能这样动规
var isSubsequence = function(s, t) {
    let n = s.length, m = t.length
    if(n == 0) return true
    if(m == 0) return false
    // dp[i][j]代表字符 j 在 t 中 i 位置第一次出现
    const dp = Array.from(Array(m + 1), () => Array(26).fill(0))
    // 为了方便状态转移,初始化所有字符都在m处第一次出现
    for(let j = 0; j < 26; j++) {
        dp[m][j] = m
    }
    for(let i = m - 1; i >= 0; i--) {
        for(let j = 0; j < 26; j++) {
            if(t[i] == String.fromCharCode(j + 'a'.charCodeAt())) {
                dp[i][j] = i
            }else {
                dp[i][j] = dp[i + 1][j]
            }
        }
    }
    let add = 0
    for(let i = 0; i < n; i++) {
        // 字符s[i]在t中第m个位置首次出现就说明没出现过,返回false
        if(dp[add][s[i].charCodeAt() - 'a'.charCodeAt()] == m) {
            return false
        }
        // 找字符s[i]在t中出现位置的下一个,因为有顺序要求
        add = dp[add][s[i].charCodeAt() - 'a'.charCodeAt()] + 1
    }
    // s中字符都查完了没出现false就是匹配的
    return true
}

猜你喜欢

转载自www.cnblogs.com/autumn-starrysky/p/13384143.html