zoukankan      html  css  js  c++  java
  • 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
    }
    
  • 相关阅读:
    SilverLight学习篇——框架搭建及实例讲述(huangyezi)
    MVVMLight学习
    MVVMLight学习篇——WPF MVVMLightToolkit(李凤桐)
    MvvmLight学习篇—— Mvvm Light Toolkit for wpf/silverlight系列(子林)
    Erro:Namespace http://schemas.microsoft.com/expression/blend/2008 is not resolved.
    MEF学习篇——MEF程序设计指南(Bēniaǒ)
    Error:The tag 'Label' does not exist in XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk'.
    silverlight页面间常用跳转模式
    UIViewController的生命周期以及相互之间通信
    解析:如何快速掌握SQL Server的锁机制
  • 原文地址:https://www.cnblogs.com/autumn-starrysky/p/13384143.html
Copyright © 2011-2022 走看看