Leetcode:NO.139 單詞拆分 動態規劃

題目

給定一個非空字符串 s 和一個包含非空單詞列表的字典 wordDict,判定 s 是否可以被空格拆分爲一個或多個在字典中出現的單詞。

說明:

拆分時可以重複使用字典中的單詞。
你可以假設字典中沒有重複的單詞。

示例 1:

輸入: s = "leetcode", wordDict = ["leet", "code"]
輸出: true
解釋: 返回 true 因爲 "leetcode" 可以被拆分成 "leet code"
示例 2:

輸入: s = "applepenapple", wordDict = ["apple", "pen"]
輸出: true
解釋: 返回 true 因爲 "applepenapple" 可以被拆分成 "apple pen apple"。
     注意你可以重複使用字典中的單詞。
示例 3:

輸入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
輸出: false

鏈接:https://leetcode-cn.com/problems/word-break

解題記錄

  • 將wordDict存入set中進行比較
  • 通過構建不同長度的字符串進行比較
/**
 * @author ffzs
 * @describe
 * @date 2020/6/25
 */
public class Solution2 {
    static int max = 0, min = Integer.MAX_VALUE;
    public static boolean wordBreak(String s, List<String> wordDict) {
        Set<String> wordSet = new HashSet<>();
        for (String s1 : wordDict) {
            wordSet.add(s1);
            max = Math.max(max, s1.length());
            min = Math.min(min, s1.length());
        }
        return wordBreak(s, 0, wordSet);
    }

    private static boolean wordBreak (String s, int start, Set<String> wordSet) {
        if (start == s.length()) return true;
        else {
            for (int i = Math.min(s.length(), start+max); i >= start + min; -- i) {
                if (wordSet.contains(s.substring(start, i)) && wordBreak(s, i, wordSet)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static void main(String[] args) {
        String s = "aaaaaaa";
        List<String> wordDict = new ArrayList<>(List.of(new String[]{"aaaa", "aaa"}));
        System.out.println(wordBreak(s, wordDict));
    }
}

在這裏插入圖片描述

暴力解法沒成,超時了。。。

優化

通過使用動態規劃進行對狀態進行記錄

  • 通過一個step數組記錄目標字符串可以通過字典中字符串拼接到的位置
  • 起始狀態是step[0]=true
  • 轉成set進行查找比list快很多
/**
 * @author ffzs
 * @describe
 * @date 2020/6/25
 */
public class Solution3 {
    static int max = 0, min = Integer.MAX_VALUE;
    public static boolean wordBreak(String s, List<String> wordDict) {
        Set<String> wordSet = new HashSet<>();
        boolean[] step = new boolean[s.length()+1];
        step[0] = true;
        for (String s1 : wordDict) {
            wordSet.add(s1);
            max = Math.max(max, s1.length());
            min = Math.min(min, s1.length());
        }

        for (int i = 0; i <= s.length()-min+1; i++) {
            for (int j = i + min; j <= s.length() && j <= i + max; j++) {
                if (step[i]) {
                    if (wordSet.contains(s.substring(i, j))){
                        step[j] = true;
                    }
                }
            }
        }
        return step[s.length()];
    }

    public static void main(String[] args) {
        String s = "aaaaaaa";
        List<String> wordDict = new ArrayList<>(List.of(new String[]{"aaa", "aaaa"}));
        System.out.println(wordBreak(s, wordDict));
    }
}

在這裏插入圖片描述

  • 通過使用HashMap對字典中的字符串通過第一個字符進行存儲
  • 更改比對的邏輯,通過第一個字符獲取到對應的字符串數據
  • 動態規劃的邏輯是一樣的
  • 匹配到最後,能夠拼成長度爲s.length則返回true否者返回false
/**
 * @author ffzs
 * @describe
 * @date 2020/6/25
 */
public class Solution4 {
    public static boolean wordBreak(String s, List<String> wordDict) {
        Map<Character, List<String>> map = new HashMap<>();
        char[] seq = s.toCharArray();
        for (String s1 : wordDict) {
            Character f = s1.charAt(0);
            if (!map.containsKey(f)){
                List<String> l = new ArrayList<>();
                l.add(s1);
                map.put(f, l);
            }else{
                map.get(f).add(s1);
            }
        }
        boolean[] step = new boolean[seq.length + 1];
        step[0] = true;
        for (int i = 0; i < seq.length ; i++) {
            if (step[i] && map.containsKey(seq[i])){
                for (String s1 : map.get(seq[i])) {
                    if (isMatch(seq, s1, i)) {
                        if (i+s1.length() == seq.length) return true;
                        step[i+s1.length()] = true;
                    }
                }
            }
        }
        return false;
    }

    private static boolean isMatch (char[] seq, String s, int start) {
        if (start + s.length() > seq.length) return false;

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) != seq[start+i]) return false;
        }

        return true;
    }

    public static void main(String[] args) {
        String s = "leetcode";
        List<String> wordDict = new ArrayList<>(List.of(new String[]{"leet", "code"}));
        System.out.println(wordBreak(s, wordDict));
    }
}

在這裏插入圖片描述

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