博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode算法编程连载之五
阅读量:6872 次
发布时间:2019-06-26

本文共 5194 字,大约阅读时间需要 17 分钟。

1、题目 - Word Break

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.For example, givens = "leetcode",dict = ["leet", "code"].Return true because "leetcode" can be segmented as "leet code".

题目解释:

指定字符串s,是否可由字典dict中的字符串组合起来进行表示?

分析:

这题很容易想到回溯法,从字符串第一个位置进行分隔,并逐步往后推移,然后开始递归确认剩余的子串,这样会有很多重复的查找。

采用动态规划,增加记忆功能,大大提高了速度。

最优解公式:dp[j] = dp[i] + EleOfSet(i, j, dict), i = 0, 1, …, j – 1

(j表示s字符串第j个位置是否可由dict的元素来表示,EleOfSet(i, j, dict)从i到j的字符串,是否是dict的元素)

边界条件:dp[0] = true;

上源码:是不是很简洁?

class Solution {public:    bool wordBreak(string s, unordered_set
&dict) { int size = s.length(); vector
dp(size + 1, false); dp[0] = true; for (int i = 1; i <= size; i ++) { for (int j = 0; j < i ; j ++) { if (dp[j] && dict.count(s.substr(j, i - j)) > 0) { dp[i] = true; } } } return dp[size]; }};

2、题目 - Distinct Subsequences

Given a string S and a string T, count the number of distinct subsequences of T in S.A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).Here is an example:S = "rabbbit", T = "rabbit"Return 3.

题目解释:

给定2个字符串S, T,求T在S中出现的次数。要求可以是不连续的,但是T在S中的顺序必须和T以前的一致。

思路:

此题很容易就想到DP来做,做完后看了下网上还是有比较多这题的解释的,但是第一次做的话,要直接想到最优解的公式还是比较难的。

刚开始想到一种方式,用空间来换时间,从s的开头进行遍历,并缓存下所有可能的字符串,运算公式如下:

dp[i] = dp[i- 1] + match_num(dp[i ]:s中第i个位置,已包含的子串T的数量,match_num:所有可能字符串,在添加s[i]后,match上子串T的数量)

class Solution {public:    int numDistinct(string s, string t) {                        int len = s.length();        int sub_len = t.length();        // 缓存下所有可能的字符串        list
possible_strs; vector
dp(len + 1, 0); list
copy_list; for (int i = 0; i < len; i ++) { char cur_ch = s[i]; string empty_str; int match_num = 0; copy_list.clear(); // 对所有可能的字符串进行遍历,看看能产生多少的匹配量,并更新可能的字符串list for (list
::iterator iter = possible_strs.begin(); iter != possible_strs.end(); iter ++) { iter->append(1, cur_ch); int str_len = iter->length(); if (iter->compare(0, str_len, t, 0, str_len) != 0) { *iter = iter->substr(0, str_len - 1); str_len = iter->length(); for (int m = str_len - 1; m >= 0; m --) { if ((*iter)[m] != cur_ch) { break; } copy_list.push_back(*iter); } continue; } if (str_len == sub_len) { match_num++; } } for (list
::iterator iter = copy_list.begin(); iter != copy_list.end(); iter ++) { possible_strs.push_back(*iter); } if (s[i] == t[0]) { string new_str; new_str.assign(1, s[i]); possible_strs.push_back(new_str); } dp[i + 1] = dp[i] + match_num; } return dp[len]; }};

很遗憾的是,由于缓存字符串list是个瓶颈,T的长度越长,要缓存的List就越大。

更好的办法

还是dp,关键是如何想到一个能够使用固定空间的最优解公式来解决这个问题,对于DP的问题,个人觉得还是多练习一些这样题目,培养这方面的思路,而且有时候,很容易思路陷进去,一维的数据记录搞不定,就一直会在那想,或者放弃了;其实可以尝试换一种思路,尝试下二维的数据,实在不行,就参考下网上其它人的思路,但问题的关键是,你一定有目标去锻炼你这方面的能力,并在做这些题目的时候,知道如何去锻炼你对算法的能力,以及你如何去扩展思考一些相关的问题。

最优解公式:

如果a[i] == b[j];则 dp[i][j] = dp[i-1][j] + dp[i-1][j-1]

如果a[i] != b[j];则 dp[i][j] = dp[i-1][j]

dp[i][j]表示:T的前j个字符在T的前i个字符中出现的次数。

边界条件:

dp[i][0] = 1,含义是:任何长度的S,如果转换为空串,那就只有删除全部字符这1种方式。

class Solution {public:    int numDistinct(string s, string t) {                        int len = s.length();        int sub_len = t.length();        vector
> dp; // 初始化二维数组 vector
tmp; for (int i = 0; i <= len; i ++) { tmp.clear(); for (int j = 0; j <= sub_len; j ++) { if (j == 0) { // 初始化,当子串为空串,只有一种情况可以转换,就是把自已的数据删除掉 tmp.push_back(1); } else { tmp.push_back(0); } } dp.push_back(tmp); } for (int i = 0; i < len; i ++) { for (int j = 0; j < sub_len; j ++) { if (s[i] == t[j]) { dp[i + 1][j + 1] = dp[i][j + 1] + dp[i][j]; } else { dp[i + 1][j + 1] = dp[i][j + 1]; } } } return dp[len][sub_len]; }};

转载于:https://www.cnblogs.com/derrick/p/4102777.html

你可能感兴趣的文章
[资源记录 ]mobile layer cdn
查看>>
关于scrapy的piplines
查看>>
内核同步机制
查看>>
用 Tornado 实现简单的在线代理
查看>>
Java写到.txt文件,如何实现换行
查看>>
JavaScript之isNaN()函数讲解
查看>>
MPlayer源代码分析
查看>>
获取音视频文件AVMetadata数据
查看>>
sql serve 创建序列
查看>>
模型层的生成
查看>>
关于APP接口设计
查看>>
【VI】如何再执行上一个(历史)命令(已解决)
查看>>
KendoUI系列:DropDownList
查看>>
Axure7.0汉化方法
查看>>
我的MYSQL学习心得(九)
查看>>
JavaScript高级程序设计学习笔记--DOM
查看>>
Python易学就会(五)turtle绘制椭圆与递归
查看>>
echarts map地图设置外边框或者阴影
查看>>
使用vue-cli脚手架+webpack搭建vue项目
查看>>
Docker - 03 编排容器 Docker Compose 指令速查表
查看>>