• 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".

    第一种思路:

    使用递归方法

    public class Solution {
        public boolean wordBreak(String s, Set<String> dict) {
            Iterator<String> iterator = dict.iterator();
            while(iterator.hasNext()){
                    String tmp = iterator.next();
                    if(s.indexOf(tmp) > -1){//s中存在tmp,可以分割
                        String[] sub = s.split(tmp);
                        int count = 0;
                        for(int i = 0; i < sub.length; i ++){
                            if(wordBreak(sub[i],dict)){
                                count++;
                            }
                        }
                        if(count == sub.length){
                            return true;
                        }
                    }
            }
            return false;
        }
    }

    Time Limit Exceeded

    分析可知,递归很耗费时间!

    public class Solution {
        public boolean wordBreak(String s, Set<String> dict) {
            int len = s.length();
            int[][] dp = new int[len][len];
            for(int i = 0 ; i < len ; i ++){
                for(int j = i ; j < len ; j ++){
                    String tmp = s.substring(i,j+1);
                    if(dict.contains(tmp)){
                        dp[i][j] = 1;//(i~j)是一个字典项
                    }
                }
            }
            return path(dp,0);
        }
        private boolean path(int[][] dp ,int index){
            if(index >= dp[0].length){
                return true;
            }
            boolean flag = false;
            for(int i = index ; i < dp[0].length; i ++){
                if(dp[index][i] == 1){
                    if(path(dp,i+1)){
                        return true;
                    }
                }
            }
            return false;
        }
    }

    思想是先寻找(i,j)是否在字典里,这样可以使用O(n2)的时间创建一副“地图“出来

    然后再从地图中找到一条路使得(0,n)无重复节点。

    Time Limit Exceeded

    string=“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab“

    dict:["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]

    dp[152*152] =

    1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0

       1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0

          1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0

             1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0

    ............

    我们发现要递归10*152+才能发现不可分割,

    而实际上我们如果注意到了“b“,那么就可以很快的确定不可分割,因为“b“在字典里没有出现

    public class Solution {
        public boolean wordBreak(String s, Set<String> dict) {
            //验证是否s里存在dict不存在的字符
                    int[] c = new int[26];
                    for(int i = 0; i < s.length(); i ++){
                            c[s.charAt(i)-'a'] = 1;
                    }
                    //for(int i = 0 ; i < 26 ; i ++){
                    //      System.out.println((char)(i+'a')+":" + (int)c[i]);
                    //}
                    for(int i = 0; i < 26 ; i ++){
                            if(c[i] == 1){
                                    int count = 0;
                                    Iterator<String> ite = dict.iterator();
                                    while(ite.hasNext()){
                                            if(ite.next().indexOf((char)(i+'a')) < 0){
                                                    count++;
                                            }
                                    }
                                    if(count == dict.size()){
                                            System.out.println("here");
                                            return false;
                                    }
    
                            }
                    }
                    //只有一个字符
                    if(s.length() == 1){
                            return true;
                    }
            
            int len = s.length();
            int[][] dp = new int[len][len];
            for(int i = 0 ; i < len ; i ++){
                for(int j = i ; j < len ; j ++){
                    String tmp = s.substring(i,j+1);
                    if(dict.contains(tmp)){
                        dp[i][j] = 1;//(i~j)是一个字典项
                    }
                }
            }
            return path(dp,0);
        }
        private boolean path(int[][] dp ,int index){
            if(index >= dp[0].length){
                return true;
            }
            boolean flag = false;
            for(int i = index ; i < dp[0].length; i ++){
                if(dp[index][i] == 1){
                    if(path(dp,i+1)){
                        return true;
                    }
                }
            }
            return false;
        }
    }

    string="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", dict:["a","aa","ba"]

    Time Limit Exceeded

    看来只能另辟蹊径了。

    原文  http://blog.csdn.net/ljphhj/article/details/21643391

    核心思想是F(0,n)= F(0,i-1)+ F(i,j-1)+F(j,n)

    public class Solution {
        public boolean wordBreak(String s, Set<String> dict) {
            boolean flag = false;
           List<Integer> list = new ArrayList<Integer>();//存储所有可能的从i到n的情况
           int len = s.length();
           for(int i = len - 1 ; i >= 0 ; i --){
               String tmp = s.substring(i);
               if(dict.contains(tmp)){//i~n是一个字典项
                   list.add(i);
               }else{//i~n不是一个字典项,那么查找是否存在j,使得F(i,n)=F(i,j)+ F(j+1,n)
                   for(Integer n : list){
                       if(dict.contains(s.substring(i,n))){//实际查询F(i,n-1)是否存在,所以不能是substring(i,n+1)
                           list.add(i);
                           break;
                       }
                   }
               }
           }
           if(list.size()==0){
              flag = false; 
           }else{
               if(list.get(list.size()-1) == 0){
                   flag = true;
               }else{
                   flag = false;
               }
           }
           return flag;
        }
    }

    string = "leetcode"

    dict=["leet","co","de","code"]

    通过上述程序,list存着什么?

    list=[6,4,0]

    string = "leetcode"

    dict=["leet","de","code"]

    通过上述程序,list存着什么?

    list=[6,4,0]

    思考可知:这两处的4是不同含义

    第一个4指的是{4,6},而第二个4是{4,n}

    也就是说上述程序的list只是找到从i到n可以使用dict分割,至于如何分割,还得分析。

    public class Solution {
        public boolean wordBreak(String s, Set<String> dict) {
            int len = s.length();
            boolean[] arrays = new boolean[len+1];
            arrays[0] = true;
            for (int i = 1; i <= len; ++i){
                for (int j = 0; j < i; ++j){
                    if (arrays[j] && dict.contains(s.substring(j, i))){
                    // f(n) = f(0,i) + f(i,j) + f(j,n)
                    arrays[i] = true; //到i是可分割的
                    break;
                    }
                }
            }
            return arrays[len];
        }
    }

    分析上述两个程序可知,思想是一致的,只不过是一个从前往后思考,一个是从后往前思考。

  • 相关阅读:
    访问网站出现EOF
    ExecutorService中submit()和execute()的区别
    JAVA设计模式之工厂模式
    使用cssQuery选择器语法来查找元素
    【转载 待读】卷积神经网络
    Python random模块(获取随机数)常用方法和使用例子
    Python 字符串操作方法大全
    Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat 解决办法
    如何在Windows 10安装和使用Linux的Bash shell
    python之内置函数
  • 原文地址:https://www.cnblogs.com/qionghua520/p/4377570.html
Copyright © 2020-2023  润新知