LeetCode-----第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

 

题目分析:

       考虑使用回溯法,先将单词使用哈希set进行存储,方便搜索。再将一个个子串切割进行对比,直到子串为空。

       结束条件:当字符串为空时,返回true

       all station:使用for循环,不需要使用全局变量index,因为传入的是子字符串作为下次递归的字符串,已经在之前的基础上进行了操作,所以不需要index,当然也可以用,这样的话传入字符串一直是s,而不是子字符串。

       优化:因为暴力回溯会有很多重复计算,在leetcode会超时,所以使用记忆化所有,遍历过的字符串就不需要再遍历了

参考代码:(暴力回溯,超时)

//暴力回溯,超时
class Solution{
public:
	bool wordBreak(string s, vector<string>& wordDict)
	{
		//初始化str_set
		unordered_set<string> str_set(wordDict.begin(), wordDict.end());

		return back_search(s, str_set);
	}

	bool back_search(string s, unordered_set<string>& str_set)
	{
		//结束条件
		if (s.empty())
		{
			return true;
		}

		for (int i = 1; i <= s.size(); i++)
		{
			if (str_set.find(s.substr(0, i)) != str_set.end())
			{
				if (back_search(s.substr(i), str_set))
					return true;
			}
		}
		return false;
	}
};

参考代码:(记忆化搜索)

//回溯,记忆化搜索
class Solution {
public:
	unordered_map<string, bool>map;//用于记忆化搜索,记忆是否遍历过
	bool wordBreak(string s, vector<string>& wordDict) 
	{
		unordered_set<string> m(wordDict.begin(), wordDict.end());
		return dfs(s , m);
	}
	bool dfs(string s, unordered_set<string>& m)
	{
		//结束条件
		if (s.empty())
		{
			return true;
		}
		//当剩余字符串搜索过不满足条件时,那么直接返回false即可
		if (map[s])
			return false;
		for (int i = 1; i <= s.size(); i++)//从1开始,很关键
		{
            //substr的第一个参数是start,第二个参数是length
			string temp = s.substr(0, i);//字符串是0~i-1
			if (m.find(temp) != m.end())//如果存在于字典中就继续操作
			{
				//将当前遍历到的子字符串切掉之后剩余部分给下次递归
				//如果不满足条件,那么将剩余字符串做个标志,下次就不需要再重复遍历了
				if (!dfs(s.substr(i), m))//从第i个字符开始到最后一个
					map[s.substr(i)] = true;
				else 
					return true;
				//if (dfs(s.substr(i), m))
				//	return true;
			}
		}
		return false;
	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值