国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

leecode 解題總結(jié):140. Word Break II

2019-11-08 02:49:53
字體:
供稿:網(wǎng)友
#include <iostream>#include <stdio.h>#include <vector>#include <string>#include <unordered_map>#include <sstream>using namespace std;/*問題:Given a non-empty string s and a dictionary WordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. You may assume the dictionary does not contain duplicate words.Return all such possible sentences.For example, givens = "catsanddog",dict = ["cat", "cats", "and", "sand", "dog"].A solution is ["cats and dog", "cat sand dog"].分析:給定一個非空字符串,確定是否可以將字符串分割為多個字符串之后,且每個字符串都在字典中。字符串的切分應(yīng)該是一個回溯的分割,一種暴力破解就是:采用回溯,得到分割結(jié)果,遍歷結(jié)果中每一個字符串,看其是否在字典中。時間復(fù)雜度應(yīng)該是O(2^n)。關(guān)鍵就是回溯的過程是怎么樣的,大致應(yīng)該是:if(pos == len){   //遍歷分割后的每個字符串是否在字典中,如果都符合,就返回true;否則返回false}for(int i = beg ; i <= len ; i++){   //判斷左邊是否在里面   sub = s.substr(i , i - beg + 1);   if(sub 在字典中)   {      result.push_back(sub);      backTrace(i+1 , s)	  //彈出之前壓入的	  result.pop_back();   }}輸入:2(字符串個數(shù)) leetcodeleet code2 leecodeleet code3 abca b c5 catsanddogcat cats and sand dog輸出:leet code空a b ccats and dog, cat sand dog又超時了,難道還是用之前的dp來做。因為dp標(biāo)記了dp[i]表示s[0...i]可以被劃分那么所有的結(jié)果應(yīng)該是找到所有dp[i] = true的地方,然后但是之前dp[i]即使為true并沒有說明s[0...i]具體應(yīng)該是怎么劃分,即沒有存儲使得dp[j] = dp[i-1] && s[i...j] in dict中的dp[i-1]應(yīng)當(dāng)需要保存下來,而且如果有多個,每一個都需要記錄也就是要記錄dp[i-1]中的位置i-1,作為上一個字符串的結(jié)尾位置如何存儲?建立一個映射map<int , vector<int>>表明dp[j]可以通過dp[i-1]獲得,如果dp[j]還可以由其他dp[k]獲得,那么就把i-1,k等這樣的全部存入到j(luò)對應(yīng)的數(shù)組中那么該map中最后一個元素應(yīng)該是n-1(假設(shè)字符串長度為n)n-1推得能夠到達(dá)dp[n-1]的其他元素,從其他元素再得到更前面的元素,逆推,即可存儲在路徑數(shù)組中,遍歷每個路徑數(shù)組做切分即可關(guān)鍵:1 回溯超時,回溯其實是對每個位置嘗試進(jìn)行分割,時間復(fù)雜度為O(2^n)。用dp,設(shè)置一個雙重循環(huán),時間復(fù)雜度為O(n^2)2 還是用dp來做,dp[i]表示s[0..i]是可以被劃分成功的,dp[j] = dp[i-1] && s[i...j] in dict,建立一個映射map<int , vector<int>>存儲能夠使得j劃分成功的所有位置對map遍歷,傳入當(dāng)前位置index,看能否找到使得該位置分割成功的之前所有位置,對每個位置遞歸查找,直到找到位置-1,存儲一個完整路徑,將所有路徑存儲后,然后切分*/class Solution {public:	//逆推獲得路徑數(shù)組,這個應(yīng)該是要遍歷的。這是遞歸還是迭代的?好像是遞歸。最后一個元素指向的位置是-1,遞歸截止,表明	void getPaths(unordered_map<int , vector<int> >& currentToPRevious , int index,		vector< vector<int> >& paths ,vector<int>& path)	{		if(currentToPrevious.empty())		{			return ;		}		//找到的最后一個位置下標(biāo)是-1,表明上一個字符串的是直接從字符串的前面部分截取而來的,這里停止遞歸,將路徑放入結(jié)果集		if(-1 == index)		{			paths.push_back(path);			return;		}		//如果找不到最后一個元素,說明不能切分		if(currentToPrevious.find( index  ) == currentToPrevious.end())		{			return ;		}		vector<int> previousArr = currentToPrevious[ index ];		if(previousArr.empty())		{			return ;		}		int size = previousArr.size();		int previousPos = -1;		for(int i = 0 ; i < size ; i++)		{			previousPos = previousArr.at(i);			//對每個位置遞歸查找			//將當(dāng)前位置插入到位置數(shù)組中			//-1不要插入,終止,直接輸出結(jié)果并檢查下一個元素			if(-1 == previousPos)			{				paths.push_back(path);				continue;			}			path.push_back(previousPos);			getPaths(currentToPrevious , previousPos , paths , path);			path.pop_back();//回溯		}	}    vector<string> wordBreak(string s, vector<string>& wordDict) {		vector<string> result;		vector<vector <string> > results;		if(s.empty() || wordDict.empty())		{			return result;		}		unordered_map<string ,bool> dict;		int size = wordDict.size();		for(int i = 0 ; i < size ; i++)		{			dict[ wordDict.at(i) ] = true;		}		int len = s.length();		vector<bool> dp(len  , false);		string str;		//dp[j]=dp[i-1] && s[i...j] in dict,其中0 <= i <=j, 0<= j < n		unordered_map<int , vector<int> > currentToPrevious;//當(dāng)前位置到上一個位置		for(int j = 0 ; j < len ; j++)		{			for(int i = 0 ; i <= j ; i++)			{				str = s.substr(i , j - i + 1); 				if(i)				{					if(dp.at(i-1) && dict.find(str) != dict.end())					{						dp.at(j) = true;						//如果已經(jīng)存儲了位置,則壓入新的結(jié)果i-1						if( currentToPrevious.find(j) != currentToPrevious.end() )						{							currentToPrevious[j].push_back(i-1);						}						else						{							vector<int> poss;							poss.push_back(i-1);							currentToPrevious[j] = poss;						}					}				}				else				{					//如果從0到當(dāng)前位置可以直接獲得,存儲位置為-1					if(dict.find(str) != dict.end())					{						dp.at(j) = true;						if( currentToPrevious.find(-1) != currentToPrevious.end() )						{							currentToPrevious[j].push_back(i-1);						}						else						{							vector<int> poss;							poss.push_back(-1);							currentToPrevious[j] = poss;						}					}				}			}		}		bool isOk = dp.at(len - 1);		if(!isOk)		{			return vector<string>();		}		//逆推獲得路徑數(shù)組		vector<vector<int> > paths;		vector<int> path;		path.push_back(len - 1);		//插入最后一個位置		getPaths(currentToPrevious , len - 1 , paths , path);		//切分字符串		result.clear();		if(paths.empty())		{			return result;		}				size = paths.size();		for(int i = 0 ; i < size ; i++)		{			len = paths.at(i).size();			stringstream stream;			//獲得的路徑是逆序的,必須逆置一下			reverse(paths.at(i).begin() , paths.at(i).end());			for(int j = 0 ; j < len ; j++)			{				if(j)				{					str = s.substr( paths.at(i).at(j-1) + 1 , paths.at(i).at(j) - paths.at(i).at(j-1) );					stream << " " << str;				}				else				{					str = s.substr(0, paths.at(i).at(j) + 1);					stream << str;				}			}			result.push_back(stream.str());		}		return result;    }};void print(vector<string>& result){	if(result.empty())	{		cout << "no result" << endl;		return;	}	int size = result.size();	for(int i = 0 ; i < size; i++)	{		cout << result.at(i) << ",";	}	cout << endl;}void process(){	 vector<string> nums;	 string str;	 string value;	 int num;	 Solution solution;	 vector<string> result;	 while(cin >> num >> str )	 {		 nums.clear();		 for(int i = 0 ; i < num ; i++)		 {			 cin >> value;			 nums.push_back(value);		 }		 result = solution.wordBreak(str , nums);		 print(result);	 }}int main(int argc , char* argv[]){	process();	getchar();	return 0;}/*	void backTrace(string& s , int beg , vector<string>& result, unordered_map<string , bool>& dict,		vector<vector <string> >& results)	{		if(s.empty() || beg < 0)		{			return;		}		int len = s.length();		//如果到達(dá)末尾,說明得到結(jié)果,返回true		if(beg == s.length())		{			results.push_back(result);			return;		}		string str;		for(int i = beg ; i < len; i++)		{			str = s.substr(beg , i - beg + 1);			//左半部分在字典中,才繼續(xù)遞歸處理			if(dict.find(str) != dict.end())			{				result.push_back(str);				//如果回溯成功,直接返回				backTrace(s , i + 1 , result , dict ,results);				result.pop_back();			}		}	}    vector<string> wordBreak2(string s, vector<string>& wordDict) {		vector<string> result;		vector<vector <string> > results;		if(s.empty() || wordDict.empty())		{			return result;		}		unordered_map<string ,bool> dict;		int size = wordDict.size();		for(int i = 0 ; i < size ; i++)		{			dict[ wordDict.at(i) ] = true;		}		backTrace(s , 0 , result , dict , results);		//拼接結(jié)果		result.clear();		if(results.empty())		{			return result;		}		size = results.size();		int len;		for(int i = 0 ; i < size ; i++)		{			len = results.at(i).size();			stringstream stream;			for(int j = 0 ; j < len ; j++)			{				if(j)				{					stream << " " << results.at(i).at(j);				}				else				{					stream << results.at(i).at(j);				}			}			result.push_back(stream.str());		}		return result;    }*/
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 张北县| 昌黎县| 花莲县| 双柏县| 托克逊县| 噶尔县| 顺昌县| 宁波市| 革吉县| 上虞市| 汝南县| 景泰县| 连江县| 远安县| 蚌埠市| 淳安县| 富顺县| 宜宾市| 金川县| 上杭县| 昆山市| 宁晋县| 屯门区| 钟山县| 泰顺县| 沙坪坝区| 铜陵市| 巴塘县| 河间市| 揭阳市| 海林市| 崇州市| 仲巴县| 喀喇沁旗| 广南县| 额尔古纳市| 泗水县| 平舆县| 徐州市| 长宁区| 淳安县|