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. [hdu2594]kmp水题

    题意:求最长的a的前缀同时满足是b的后缀,把a,b连在一起,kmp跑一下,迭代next直到长度小于等于a,b长度的最小值为止,即为答案. #pragma comment(linker, "/ ...

  2. 在微服务框架Demo.MicroServer中添加SkyWalking+SkyApm-dotnet分布式链路追踪系统

    1.APM工具的选取 Apm监测工具很多,这里选用网上比较火的一款Skywalking. Skywalking是一个应用性能监控(APM)系统,Skywalking分为服务端Oap.管理界面UI.以及 ...

  3. 帝国cms 批量替换 字段内容包含的 指定的 关键字 SQL命令

    帝国cms 批量替换 字段内容包含的 指定的 关键字update phome_ecms_news_data_1 set newstext=replace(newstext,'原来','现在');

  4. C++内存管理学习笔记(2)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  5. poi excel自动转换成javabean 支持引用类型属性二级转换

    最近项目需要使用excel导入功能,导入学生的时候需要指定所在班级,使用excel一次性导入! 将以前的代码改改支持属性内引用类的转换. 测试对象为User对象,javabean结构: private ...

  6. 2018-06-26 jq选择器

    0.选择器的目的就是为了方便快速找到元素从而操作元素! 1.基本选择器 *  -> 所有标签 #id ->id选择器 .class -> 类选择器 h1,h2 -> 组合选择器 ...

  7. jquery监听input

    $(function(){ //输入框正在输入时 $("#ipt").on('input',function(){ if(!($('#ipt').val()=='')){ $(&q ...

  8. vue中v-for索引不要用key

    今天发现在给元素v-for渲染的时候,想给元素添加key特性存储索引,发现不奏效: <div class="apic" v-for="(pic,index) in ...

  9. react中控制元素的显示与隐藏

    1.通过 state 变量来控制是否渲染元素 类似于 vue 的 v-if 方法是通过变量来控制是否加载元素的,如果变量为false,内容就直接不会渲染的. class Demo extends Re ...

  10. 苏浪浪 201771010120 《面向对象程序设计(java)》第9周学习总结

    实验九异常.断言与日志 实验时间 2018-10-25 1.实验目的与要求 (1) 掌握java异常处理技术: (2) 了解断言的用法: (3) 了解日志的用途: (4) 掌握程序基础调试技巧: 2. ...