leetcode之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, given
s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".

此題有點兒難度,但其實應該是能夠想起用遞歸求解的,即針對遍歷的每個位置將字符串分爲兩部分,若前一部分在字典中,則只需遞歸求解剩餘子串是否在字典中,這裏需要注意的是遞歸返回true值的條件。這種方法很明顯存在很多冗餘的比較。

bool wordBreak(string s, unordered_set<string> &dict) {
		bool b = false;
		for(int i = 1; i <= s.size(); i++){
			string str = s.substr(0,i);
			if(dict.find(str) != dict.end()){
				if(i == s.size())
					return true;
				string subStr =  s.substr(i);
				b = wordBreak(subStr,dict);		
				if(b)
				return true;
	 	    }
		}			
		return false;
	}
在上題的基礎上可以採用動態規劃的方法來減少冗餘的比較,其思路是:長度爲len的字符串共有len + 1 種分割方法將其分爲兩部分,所以可以創建一個len + 1 大小的bool向量bv來存儲字典中是否包含以當前分割的左半部分的字符串,首先賦初值bv[0] = true;然後依次遍歷求解後邊的分割方法,針對每次分割的左半部分,再次遍歷分割的左半部分,這樣在判斷時可以在之前以求解的基礎上進行簡化,當發現存在組合時即可提前結束遍歷。最終bv[len]即爲所求。

bool wordBreak(string s, unordered_set<string> &dict) {
		vector<bool>bv(s.size() + 1,false);
		bv[0] = true;
		for(int i = 1;i <= s.size(); i++){
			for(int j = 0; j < i; j++){
				if(bv[j] == true && dict.find(s.substr(j,i - j)) != dict.end())
				{
				    bv[i] = true;
					break;
				}
			}
		}
		return bv[s.size()];
    }

這道題雖然有難度,但其求解思路和優化方法是逐步深入和有跡可循的,還是要加強練習、記憶、和總結才行。

補:

    按照第二種思路Python實現如下:

class Solution:
    # @param s, a string
    # @param dict, a set of string
    # @return a boolean
    def wordBreak(self, s, dict):
        L = []
        for i in range(len(s)):
            L.append(False)
        L.append(False)
        L[0] = True
        for i in range(len(s)) :
            for j in range(len(L)):
                str = s[j:i + 1]
                if L[j] == True  and  str in dict:
                    L[i + 1] = True
                    break
        return L[-1]
在leetcode上實現的第一個Python代碼哦,紀念一下~



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章