[leetcode 7] word-break-ii

17 篇文章 0 订阅

题目描述
给定一个字符串s和一组单词dict,在s中添加空格将s变成一个句子,使得句子中的每一个单词都是dict中的单词
返回所有可能的结果
例如:给定的字符串s =“catsanddog”,
dict =[“cat”, “cats”, “and”, “sand”, “dog”].
返回的结果为[“cats and dog”, “cat sand dog”].

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s =“catsanddog”,
dict =[“cat”, “cats”, “and”, “sand”, “dog”].
A solution is[“cats and dog”, “cat sand dog”].

每次做动态规划的题目总是能让我产生我可能不适合写代码的想法,这道题目更是虐哭我…
动态规划算法,我的理解,就是通过记录一些信息,避免对某些情况的重复计算,从而减少递归次数。
原理很简单,可真正写起来各种问题都出来了…最终通过不断的调试终于通过了…不容易…

思路:

  • 和word-break的第一题一样,这道题也是对字符串s进行拆分,不过这一题要求把拆分后的每个单词间加上空格输出出来。既然要加空格,首先得知道s拆成了哪些单词,所以我用了一个vector(tem)来存拆分后的单词,用另一个vector(res)来存拆分成功的字符串;
  • 一旦拆分成功了就把tem中的单词用空格串起来,push到res里。总体思路和word-break很像,代码似乎不复杂,但调试过程真心累,直接看代码吧。

这里还要吐槽一下牛客网的评分标准,顺序不一样就直接给错了,太不智能了!!

本来就难还这么严格,于是愤怒投奔leetcode,终于通过了~~

代码:

class Solution {
public:
    vector<string> wordBreak(string s, vector<string>& wordDict) {
    	if (s.length() == 0)
		    return res;
		bool *dp = new bool[s.length() + 1];
		memset(dp, 0, s.length() + 1);
        unordered_set<string> dict;
        for (int i=0; i<wordDict.size(); i++)
            dict.insert(wordDict[i]);
		BreakWord(s, dict, dp);
		return res;
    }
    void BreakWord(string s, unordered_set<string> &dict, bool *cannot)
	{
		int len = s.length();
		if (len == 0 && !tem.empty()) // 当拆分成功时,把单词间加上空格后的字符串push到res里
		{
			string str;
			for (int i = 0; i < tem.size() - 1; i++)
			{
				str += tem[i];
				str += " ";
			}
			str += tem[tem.size() - 1];
			res.push_back(str);
		}
		if (cannot[len]) // 如果已知不能拆分,直接return
			return;
        int ressize = res.size(); // 记录是否成功拆分
		for (int i = 1; i <= len; i++)
		{
			string tmp = s.substr(0, i);
			if (dict.find(tmp) != dict.end())
			{
				tem.push_back(tmp);
				BreakWord(s.substr(i, len - i), dict, cannot);
				tem.pop_back(); // 不论有没有拆分成功,都要pop掉tmp
			}
        }
	    if (res.size() == ressize) // 如果为true,则表示没能成功拆分,做好记录防止重复计算
		    cannot[len] = true;
	}
private:
	vector<string> res;
	vector<string> tem;
};

大佬们的代码:

vector<string> wordBreak(string s, unordered_set<string> &dict) {
       vector<string> res;
       if(dict.find(s) != dict.end())    res.push_back(s);
       int len = s.size();
       for(int i=1; i< len; ++i){
           string word = s.substr(i);
           if(dict.find(word) == dict.end()) continue;
           vector<string> tempRes = wordBreak(s.substr(0, i), dict);
           Combine(tempRes, word);
           res.insert(res.begin(), tempRes.begin(), tempRes.end());
       }
       return res;
   }
   void Combine(vector<string>& v, const string& str){
       for(auto& e : v)  { e +=" " + str;}
   }

瞅瞅这是人能写出来的吗?才这几行?
今天零食吃完了,明天再看zz

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值