当前位置: 首页 > news >正文

免费网站建站塔山双喜it外包项目做完了就解散了吗

免费网站建站塔山双喜,it外包项目做完了就解散了吗,东莞网络营销推广软件,网站怎么推广最139. 单词拆分 (求排列方法) 题目链接🔥🔥 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明: 拆分时可以重复使用字典中的单词。 你可以假设字典中没…

139. 单词拆分 (求排列方法)

题目链接🔥🔥
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。

示例 1:
输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。

示例 2:
输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true
解释: 返回 true 因为 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重复使用字典中的单词。

示例 3:
输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出: false

回溯思路分析

之前讲解回溯法专题的时候,讲过的一道题目回溯算法:分割回文串,就是枚举字符串的所有分割情况。
本道是枚举分割所有字符串,判断是否在字典里出现过。
回溯法C++代码:(会超时)

class Solution {
private:bool backtracking (const string& s, const unordered_set<string>& wordSet, int startIndex) {if (startIndex >= s.size()) {return true;}for (int i = startIndex; i < s.size(); i++) {string word = s.substr(startIndex, i - startIndex + 1);if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, i + 1)) {return true;}}return false;}
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());return backtracking(s, wordSet, 0);}
};

递归的过程中有很多重复计算,可以使用数组保存一下递归过程中计算的结果。

这个叫做记忆化递归,这种方法我们之前已经提过很多次了。

使用memory数组保存每次计算的以startIndex起始的计算结果,如果memory[startIndex]里已经被赋值了,直接用memory[startIndex]的结果。

C++代码如下:

class Solution {
private:bool backtracking (const string& s,const unordered_set<string>& wordSet,vector<bool>& memory,int startIndex) {if (startIndex >= s.size()) {return true;}// 如果memory[startIndex]不是初始值了,直接使用memory[startIndex]的结果if (!memory[startIndex]) return memory[startIndex];for (int i = startIndex; i < s.size(); i++) {string word = s.substr(startIndex, i - startIndex + 1);if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, memory, i + 1)) {return true;}}memory[startIndex] = false; // 记录以startIndex开始的子串是不可以被拆分的return false;}
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());vector<bool> memory(s.size(), 1); // -1 表示初始化状态return backtracking(s, wordSet, memory, 0);}
};

背包思路分析

单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。

拆分时可以重复使用字典中的单词,说明就是一个完全背包!

动规五部曲分析如下:

  1. 确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。

  1. 确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

  1. dp数组如何初始化

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

那么dp[0]有没有意义呢?

dp[0]表示如果字符串为空的话,说明出现在字典里。

但题目中说了“给定一个非空字符串 s” 所以测试数据中不会出现i为0的情况,那么dp[0]初始为true完全就是为了推导公式。

下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

  1. 确定遍历顺序

题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。

还要讨论两层for循环的前后顺序。

如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品

而本题其实我们求的是排列数,为什么呢。 拿 s = “applepenapple”, wordDict = [“apple”, “pen”] 举例。

“apple”, “pen” 是物品,那么我们要求 物品的组合一定是 “apple” + “pen” + “apple” 才能组成 “applepenapple”。

“apple” + “apple” + “pen” 或者 “pen” + “apple” + “apple” 是不可以的,那么我们就是强调物品之间顺序。

所以说,本题一定是 先遍历 背包,再遍历物品。

如果先遍历物品再遍历背包

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());vector<bool> dp(s.size() + 1, false);dp[0] = true;for (int j = 0; j < wordDict.size(); j++) { // 物品for (int i = wordDict[j].size(); i <= s.size(); i++) { // 背包string word = s.substr(i - wordDict[j].size(), wordDict[j].size());// cout << word << endl;if ( word == wordDict[j] && dp[i - wordDict[j].size()]) {dp[i] = true;}// for (int k = 0; k <= s.size(); k++) cout << dp[k] << " "; //这里打印 dp数组的情况 // cout << endl;}}return dp[s.size()];}
};

使用用例:s = “applepenapple”, wordDict = [“apple”, “pen”],对应的dp数组状态如下:
在这里插入图片描述
最后dp[s.size()] = 0 即 dp[13] = 0 ,而不是1,因为先用 “apple” 去遍历的时候,dp[8]并没有被赋值为1 (还没用"pen"),所以 dp[13]也不能变成1。

除非是先用 “apple” 遍历一遍,再用 “pen” 遍历,此时 dp[8]已经是1,最后再用 “apple” 去遍历,dp[13]才能是1。

  1. 举例推导dp[i]
    在这里插入图片描述

代码实现

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {set<string> dict(wordDict.begin(),wordDict.end());cout<<endl;vector<bool> dp(s.size()+1,false);dp[0]=true;for(int j=0;j<=s.size();j++){   // 遍历背包for(int i=0;i<j;i++){       // 遍历物品if(dict.find(s.substr(i,j-i))!=dict.end()&&dp[i]!=false){//substr(起始位置,截取的个数)dp[j]=true;}}}return dp[s.size()];}
};

思考总结

再理解一下这里为什么是排列不是组合。


http://www.yayakq.cn/news/324130/

相关文章:

  • 铁法能源公司网站图片高清处理在线
  • 网站建设先进个人总结手机可以制作app软件吗
  • 协达网站建设wordpress改为直接填写密码
  • 天津网站建设案例展示广宁县住房和城乡建设局网站
  • 网站建设销售问答定制营销型网站什么意思
  • 怎么用手机黑网站wordpress 菜单去掉链接
  • 为什么做不了自己的网站番禺哪里有做网站的公司
  • 科讯网站模版网网站建设实施
  • 做知识问答的网站代理服务器地址是什么意思
  • 黄浦区seo网站建设wordpress 登录空白
  • 郑州网站建设专家网站四网合一
  • 个人网站建设计划报告企信网企业信息查询平台官网
  • 网站图片设计怎样才能高大上企查查询官网入口
  • 巴彦淖尔市网站建设济南百度网站开发
  • 网站开发基础课程wordpress 图片展示插件
  • 建设旅游网站的好处wordpress搜索调用
  • 网站建设不完整什么意思河南华盛建设集团网站
  • 2018年网站建设的数据佛山做网站需要多少钱
  • 给分管领导网站建设情况汇报怎么写推广一个app的费用
  • 中国建设网官方网站6wordpress左图右字
  • 用php做网站需要什么网站假设公司排名
  • 开发网站五个阶段批量替换wordpress页面文字
  • 学校网站 cms深圳网络推广软件
  • wordpress仿站网在线图片制作生成
  • 哪个网站有建设需要等文件象山网站优化公司
  • 哪家网站遴选做的比较好html菜鸟入门教程
  • 建一个做笔记的网站叮当app制作平台下载
  • html5 网站模板国内最新消息新闻
  • 多元国际二维码图片福州seo网站推广优化
  • 长沙的互联网网站公司wordpress自定义菜单插件