LeetCode-139-單詞拆分

雄獅虎豹 發表於 2022-01-26
LeetCode

單詞拆分

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

說明:

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

示例說明請見LeetCode官網。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/probl...
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

解法一:窮舉法

使用窮舉+遞迴的方式求解,效率較低,具體處理過程如下:

  • 如果當前字串為null或者為空字串,則預設可以由字串字典切分,直接返回true;
  • 否則,遍歷字串字典中的字串:

    • 如果某個字串剛好和當前字串相等並且長度一致,則直接返回true;
    • 如果某個字串和當前字串相等但是長度不一致,遞迴判斷後面的字串並返回判斷的結果。
  • 最後,返回最終判斷的結果。
解法二:動態規劃
  • 首先,初始化字串字典到雜湊表wordDictSet中,便於快速查詢;
  • 然後初始化一個dp陣列,陣列的長度為原始字串的長度加1,並初始化陣列的第一個元素為true;
  • 然後遍歷字串,判斷從0到i的字串是否可以由字串字典切分而成:

    • 判斷邏輯是從0到j的字串可以由字串字典切分(這個根據前面的計算得到) 並且 從j到i 的字串在字串字典中。
  • 最終,返回dp陣列的最後一個元素即為最終結果。
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class LeetCode_139 {
    private static boolean flag = false;

    /**
     * 窮舉法
     *
     * @param s
     * @param wordDict
     * @return
     */
    public static boolean wordBreak(String s, List<String> wordDict) {
        if (s == null || s.length() == 0) {
            return true;
        }

        for (String word : wordDict) {
            if (flag) {
                return flag;
            }
            if (s.startsWith(word)) {
                if (s.length() == word.length()) {
                    // 如果當前字元與字串字典中的某個字串匹配並且長度相同,則說明當前字串可以由字串字典切分成,返回true
                    return true;
                }
                // 如果當前字串由某個字串字典中的字串切分後,還有待判斷的字元,則遞迴判斷後面的字串
                flag = wordBreak(s.substring(word.length()), wordDict);
            }
        }
        return flag;
    }

    /**
     * 動態規劃
     *
     * @param s
     * @param wordDict
     * @return
     */
    public static boolean wordBreak2(String s, List<String> wordDict) {
        // 初始化字串字典到雜湊表中,便於快速查詢
        Set<String> wordDictSet = new HashSet<>(wordDict);
        boolean[] dp = new boolean[s.length() + 1];
        // 預設空字串可以由字串字典切分而成,初始置為true
        dp[0] = true;

        // 判斷從0到i的字串是否可以由字串字典切分而成
        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i; j++) {
                // 判斷邏輯是從0到j的字串可以由字串字典切分(這個根據前面的計算得到) 並且 從j到i 的字串在字串字典中
                if (dp[j] && wordDictSet.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[s.length()];
    }

    public static void main(String[] args) {
        String s = "applepenapple";
        List<String> wordDict = new ArrayList<>();
        wordDict.add("apple");
        wordDict.add("pen");

        System.out.println(wordBreak(s, wordDict));
        System.out.println(wordBreak2(s, wordDict));
    }
}
【每日寄語】 要相信機會總是會有的,不要和自己較勁,要順勢,像太極推手一樣,順勢而為,要學會利用周邊資源。