Leetcode中字符串与break(一)

字符串一直以来都是我不擅长处理的题目,解题思路一般两种 BF 和 DP,我一般BF不行了就直接DFS (Backtracking?)。先上几道题目,看看有没有什么共同特征。


题目一:Word Break

先来一发简单的,我都不知道算不算得上是DP了,反正是一维的而且还有记录本啥的。

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one dictionary words. For example, given s="leetcode", dict=["leet", "code"], return true.

思路:这道题只用返回TRUE or FALSE。最开始我二逼的将字符串一个个单词切分匹配,不仅有递归而且还有大量的substr。。。通过某道题的启发(Jump?)想到一个O(n)的方法而逆袭成功。想想递推式~~据目前的情形看来,在字符串匹配及变形题中用递归貌似都有点二逼。

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        int sz=s.length();
        if(sz==0) return false;
        bool c[sz+1];
        for(int i=1;i<sz+1;i++) c[i]=false;
        c[0]=true;
        
        for(int i=0;i<sz;i++){
			if(c[i]){
				unordered_set<string>::iterator it=dict.begin();
				for(;it!=dict.end();it++){
					string newstr=s.substr(0,i)+*it;
					if(s.find(newstr)<s.length())
						c[newstr.length()]=true;	
				}
			}
		}
	    return c[sz];
    }
};

题目二: Word Break II

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 senstences. For example, given s="catsanddog", dict=["cat", "cats", "and", "sand", "dog"], a solution is ["cats and dog", "cat sand dog"].

第一道题水水就行了,看到这道题要呆掉了,尼玛貌似之前的方法完全不能用嘛!还是重操旧业——递归,可以枚举出所有的解,这大概是递归最大的优点吧。如果只用递归的话,也会出现Word break中的TLE问题,因为存在很多没有必要的枚举,故放在前面的解法,做一个记录本, 记录范围过的[1..s.size()-1]中访问过的点。

class Solution {
private:
    int lmin, lmax;
public:
    vector<string> wordBreak(string s, unordered_set<string> &dict) {
        vector<string> res;
        string words="";
        map<int, bool> valid;
        lmin=1<<12; lmax=0;
        
        for(unordered_set<string>::iterator it=dict.begin(); it!=dict.end(); it++){
            if(it->length()<lmin) lmin=it->length();
            if(it->length()>lmax) lmax=it->length();
        }
        
        doWordBreak(s, dict, res, words, valid, 0);
        return res;
    }
    
    bool doWordBreak(string s, unordered_set<string>& dict, vector<string >& res, string words, map<int, bool>& valid, int lev){
        if(lev>=s.length()){ 
            res.push_back(words.substr(0, words.length()-1));
            return true;
        }
        if(valid.count(lev) && valid[lev]==false) 
            return false;
            
        int flag=false;
        for(int i=lmin; i<=lmax && i+lev<=s.length(); i++){
            string tmp=s.substr(lev,i);
            if(dict.count(tmp)){
                if(doWordBreak(s, dict, res, words+tmp+" ", valid, lev+i)){
                    flag=true;
                    valid[lev+i]=true;
                }
                else valid[lev+i]=false;
            }
        }
        return flag;
    }
};


上面两题都是带字典的break words, 下面这道这是纯的字符串的划分。


题目三:Restore IP Addresss

Given a string containing only digits, restore it by returning all possible valid IP address combinations. For example: Given "25525511135",  return ["255.255,11.135", "255.255.111.35"].

思路:IP地址有自己固有的格式。这导致输入字符串长度必须在[4, 12], 其没三位的数值不超过255. 这样要列出所有的可能解,递归是比较直接的选择,但是这样考虑到字符串格式固定且长度优先,直接3层循环就可以了。

class Solution {
public:
    vector<string> restoreIpAddresses(string s) {
        vector<string> res;
        //异常输入处理!
        if (s.size() > 12 || s.size() < 4)
            return res;
            
        for(int i=1;i<4;i++){
            string first=s.substr(0,i);
            if(!isValid(first)) continue;
            for(int j=1;i+j<s.size()&&j<4; j++){
                string second=s.substr(i,j);
                if(!isValid(second)) continue;
                for(int k=1;i+j+k<s.size()&&k<4;k++){
                    string third=s.substr(i+j,k);
                    string fourth=s.substr(i+j+k);
                    if(isValid(third) && isValid(fourth)){
                        string ip=first+"."+second+"."+third+"."+fourth;
                        res.push_back(ip);
                    }
                }
            }
        }
        return res;
    }
    
    bool isValid(string s){
        if(s.size()>1 && s[0]=='0') return false;  //如果是两位或以上且首位为0,则不合格
        if(stoi(s)>=0 && stoi(s)<=255) return true; //高级用法stoi!
        else return false;
    }
};




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值