115. 不同的子序列

给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。

一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,“ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)

示例 1:

输入: S = “rabbbit”, T = “rabbit”

输出: 3

解释:

如下图所示, 有 3 种可以从 S 中得到 “rabbit” 的方案。

(上箭头符号 ^ 表示选取的字母)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^

示例 2:

输入: S = “babgbag”, T = “bag”

输出: 5

解释:

如下图所示, 有 5 种可以从 S 中得到 “bag” 的方案。

(上箭头符号 ^ 表示选取的字母)

babgbag
^^ ^
babgbag
^^ ^
babgbag
^ ^^
babgbag
^ ^^
babgbag
^^^

PS:

还是佩服大佬们的面向测试用例编程

 /**
* 动态规划 但是效率并不高 20ms 35.83%
* 大部分都是二维动态规划 有的代码相同但是是5ms 估计是测试用例有变动
* 但是看到还是有节省的算法 所以一步一步往下优化
*
* * b a b g b a g
* * 1 1 1 1 1 1 1 1
* b 0 1 1 2 2 3 3 3
* a 0 0 1 1 1 1 4 4
* g 0 0 0 0 1 1 1 5
* @param s
* @param t
* @return
*/
public int numDistinct(String s, String t) {
int[][] dp = new int[t.length() + 1][s.length() + 1];
//初始化第一行
for(int j = 0; j <= s.length(); j++){
dp[0][j] = 1;
} for(int i = 1; i <= t.length(); i++){
for(int j = 1; j <= s.length(); j++){
if(t.charAt(i-1) == s.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + dp[i][j-1];
}else {
dp[i][j] = dp[i][j-1];
}
}
}
return dp[t.length()][s.length()];
} /**
* 二维换一维 严格按照二维的流程 参见上面矩阵 这个是15ms
* @param s
* @param t
* @return
*/
public int numDistinct2(String s, String t) {
int[] dp = new int[s.length() + 1];
Arrays.fill(dp, 1);
int pre = 1;
//每行算一次
for(int i = 0; i < t.length(); i++){
//0-n算n+1次
for(int j = 0; j <= s.length(); j++){
//先保存dp[j]下次用
int temp = dp[j];
if(j == 0){
dp[j] = 0;
}else {
if(t.charAt(i) == s.charAt(j-1)){
dp[j] = dp[j-1] + pre;
}else {
dp[j] = dp[j-1];
}
}
pre = temp;
}
}
return dp[s.length()];
} /**
* 列主序 倒序计算 就不用保存临时值pre了
* 可以按上图二维矩阵的顺序模仿一下 这个是11ms
* @param s
* @param t
* @return
*/
public int numDistinct3(String s, String t) {
// dp[0]表示空串
int[] dp = new int[t.length() + 1];
// dp[0]永远是1,因为不管S多长,都只能找到一个空串,与T相等
dp[0] = 1; for (int i = 0; i < s.length(); i++){
for (int j = t.length() - 1; j >= 0; j--) {
if (t.charAt(j) == s.charAt(i)) {
dp[j + 1] += dp[j];
}
}
}
return dp[t.length()];
} /**
* 列主序 先构造字典 就不用遍历t了
* 这样就优化成了答案上的2ms的了
* @param s
* @param t
* @return
*/
public int numDistinct4(String s, String t) {
// dp[0]表示空串
int[] dp = new int[t.length() + 1];
// dp[0]永远是1,因为不管S多长,都只能找到一个空串,与T相等
dp[0] = 1; //t的字典
int[] map = new int[128];
Arrays.fill(map, -1); //从尾部遍历的时候可以遍历 next类似链表 无重复值时为-1,
//有重复时例如从rabbit的b开始索引在map[b] = 2 next[2] 指向下一个b的索引为3
// for (int j = t.length() - 1; j >= 0; j--) {
// if (t.charAt(j) == s.charAt(i)) {
// dp[j + 1] += dp[j];
// }
// }
//这段代码的寻址就可以从map[s.charAt(i)] 找到索引j 在用next[j] 一直找和 s.charAt(i)相等的字符 其他的就可以跳过了
//所以这个代码的优化 关键要理解 上面的一维倒算
int[] nexts = new int[t.length()];
for(int i = 0 ; i < t.length(); i++){
int c = t.charAt(i);
nexts[i] = map[c];
map[c] = i;
} for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
for(int j = map[c]; j >= 0; j = nexts[j]){
dp[j + 1] += dp[j];
}
}
return dp[t.length()];
}

Java实现 LeetCode 115 不同的子序列的更多相关文章

  1. Java for LeetCode 115 Distinct Subsequences【HARD】

    Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence ...

  2. Leetcode 115.不同的子序列

    不同的子序列 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串.(例 ...

  3. Java实现 LeetCode 152 乘积最大子序列

    152. 乘积最大子序列 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] ...

  4. LeetCode 115.不同的子序列 详解

    题目详情 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串.(例如, ...

  5. leetcode 115不同的子序列

    滚动数组: /***** 下标从1开始 dp[i][j]:= numbers of subseq of S[1:j] equals T[1:i] if(s[j]==t[i]):(那么之后的子串可以是是 ...

  6. Java for LeetCode 216 Combination Sum III

    Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...

  7. Java for LeetCode 214 Shortest Palindrome

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  8. Java for LeetCode 212 Word Search II

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

  9. Java for LeetCode 211 Add and Search Word - Data structure design

    Design a data structure that supports the following two operations: void addWord(word)bool search(wo ...

随机推荐

  1. CODING 敏捷实战系列课第三讲:可视化业务分析

    业务分析处在开发过程的上游,提高业务分析的质量,可以减少后续开发.测试和集成过程中的反复确认,场景遗漏.采用可视化的业务分析工具箱可以大幅度避免文字版的业务需求描述所带来的不够完整,有误解等问题.CO ...

  2. linux --开机自动挂载硬盘【转】

    转:http://c.biancheng.net/view/900.html 了解了 mount 命令之后,读者可能会问,系统如何在开机时自动挂载硬盘,它又是怎么知道哪些分区是需要挂载的呢? 很简单, ...

  3. php_rce

    0x01 PHP_RCE RCE(remote command/code execute):远程命令/代码执行 此题为ThinkPHP V5远程代码执行漏洞 0x02 命令执行 http://124. ...

  4. Cannot parse "1986-05-04": Illegal instant due to time zone offset transition (Asia/Shanghai)

    调查系统错误时,发现了一个很奇怪的现象,出生日期1986-05-04号的用户始终无法注册.发现后台使用使用jodatime的代码demo如下: public static DateTime parse ...

  5. 00004-form 表单的清空、重置 (jquery)

    form 表单的清空.重置 $(':input').not(':button, :submit, :reset').val('').removeAttr('selected').removeAttr( ...

  6. CPU 多核指令 —— WFE 原理【原创】

    转自:http://tinylab.org/arm-wfe/ Zhang Binghua 创作于 2020/05/19 打赏 微信公众号   知识星球 关注 @泰晓科技 与数千位一线 Linux 工程 ...

  7. css概述三

    五.盒子模型 4.box-sizing 定义盒子模型的计算方式 box-sizing:content-box; 默认值,我们定义的width/height是内容区域 元素占地宽度=左外边距+左边框+左 ...

  8. 快速配置Samba服务

    1.安装samba 这里以CenOS 7为例,其他系统类似 yum install samba samba-client samba-common   2.修改smb.conf 最好先备份原文件,以防 ...

  9. Appium自动化(15) - 针对 webview 进行自动化测试

    如果你还想从头学起Appium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1693896.html webview 简介 WebVie ...

  10. STM32F103出现CPU could not be halted问题的解决方案

    问题描述: **JLink Warning: CPU could not be halted ***JLink Error: Can not read register 15 (R15) while ...