题目

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

Note:

  • The same word in the dictionary may be reused multiple times in the segmentation.
  • You may assume the dictionary does not contain duplicate words.

Example 1:

  1. Input: s = "leetcode", wordDict = ["leet", "code"]
  2. Output: true
  3. Explanation: Return true because "leetcode" can be segmented as "leet code".

Example 2:

  1. Input: s = "applepenapple", wordDict = ["apple", "pen"]
  2. Output: true
  3. Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
  4. Note that you are allowed to reuse a dictionary word.

Example 3:

  1. Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
  2. Output: false

题意

判断给定字符串按照某种方式分割后得到的所有子串能否在给定数组中找到。

思路

  1. 纯DFS会超时,所以利用Map记录下所有执行过的递归的结果。
  2. 动态规划。dp[i]代表s中以第i个字符结尾的子串是否满足要求,则状态转移方程为:只要有任意一个j(j<i)满足 dp[j]==true && wordDict.contains(s.substring(j,i))==true,那么dp[i]=true。

代码实现

Java

记忆化搜索

  1. class Solution {
  2. public boolean wordBreak(String s, List<String> wordDict) {
  3. return isValid(s, 0, wordDict, new HashMap<>());
  4. }
  5. private boolean isValid(String s, int start, List<String> wordDict, Map<Integer, Boolean> record) {
  6. if (start == s.length()) {
  7. return true;
  8. }
  9. if (record.containsKey(start)) {
  10. return record.get(start);
  11. }
  12. for (int end = start + 1; end <= s.length(); end++) {
  13. if (wordDict.contains(s.substring(start, end)) && isValid(s, end, wordDict, record)) {
  14. record.put(start, true);
  15. return true;
  16. }
  17. }
  18. record.put(start, false);
  19. return false;
  20. }
  21. }

动态规划

  1. class Solution {
  2. public boolean wordBreak(String s, List<String> wordDict) {
  3. boolean[] dp = new boolean[s.length() + 1];
  4. dp[0] = true;
  5. for (int i = 1; i <= s.length(); i++) {
  6. for (int j = 0; j < i; j++) {
  7. if (dp[j] && wordDict.contains(s.substring(j, i))) {
  8. dp[i] = true;
  9. break;
  10. }
  11. }
  12. }
  13. return dp[s.length()];
  14. }
  15. }

JavaScript

  1. /**
  2. * @param {string} s
  3. * @param {string[]} wordDict
  4. * @return {boolean}
  5. */
  6. var wordBreak = function (s, wordDict) {
  7. let dp = new Array(s.length + 1).fill(false)
  8. dp[0] = true
  9. for (let i = 1; i <= s.length; i++) {
  10. for (let j = 0; j < i; j++) {
  11. if (dp[j] && wordDict.indexOf(s.slice(j, i)) >= 0) {
  12. dp[i] = true
  13. break
  14. }
  15. }
  16. }
  17. return dp[s.length]
  18. }