上午把docker基础学完了。下午来了闲的无聊,做一题先。
1、题目描述

2、逻辑分析
这个问题是一个典型的动态规划问题,我们可以使用一个布尔数组 dp 来记录字符串 s 的前缀是否可以被拆分成字典中的单词。具体地,dp[i] 表示字符串 s 的前 i 个字符(即 s.substring(0, i))是否可以被拆分成字典中的单词。
算法的基本思路是,从字符串 s 的第一个字符开始,逐步向后检查每个位置。对于每个位置 i,我们再次遍历从位置 0 到 i-1 的所有位置 j,并检查子串 s.substring(j, i) 是否在字典中。如果 s.substring(j, i) 在字典中,并且 dp[j] 为 true(即 s 的前 j 个字符可以被拆分),那么我们就可以将 dp[i] 设置为 true。
3、代码演示
public boolean wordBreak(String s, List<String> wordDict) {
        // 将字典 wordDict 转换为 HashSet,以便快速查找 
        Set<String> wordDictSet = new HashSet<>(wordDict);
        // 创建一个布尔数组 dp,dp[i] 表示 s 的前 i 个字符是否可以被拆分
        boolean[] dp = new boolean[s.length() + 1];
        // 初始化 dp[0] 为 true,因为空字符串总是可以被拆分的
        dp[0] = true;
        // 从第一个字符开始遍历到字符串末尾
        for(int i = 1; i <= s.length(); i++){
            // 从第 0 个字符到当前字符的前一个字符进行遍历(包含)
            for(int j = 0; j < i; j++){
                // 如果 s 的前 j 个字符可以被拆分(即 dp[j] 为 true)  
                // 并且 s 的从第 j 个字符到当前字符的子串在字典中
                //(即 wordDictSet.contains(s.substring(j, i)) 为 true)
                if(dp[j] && wordDictSet.contains(s.substring(j, i))){
                    // 那么 s 的前 i 个字符也可以被拆分,设置 dp[i] 为 true
                    dp[i] = true;
                    // 因为已经找到了一个拆分方式,所以可以提前跳出内层循环
                    break;
                }
            }
        }
        // 返回 s 是否可以被完全拆分,即 dp[s.length()] 是否为 true
        return dp[s.length()]; 
    }
 
以字符串 s = “leetcode” 和字典 wordDict = ["leet", "code"] 为例来解释这段代码。
- 首先,我们初始化一个长度为 
9的布尔数组dp,所有元素都初始化为false,除了dp[0],它表示空字符串,所以初始化为
true。 - 然后,我们开始遍历字符串 
"leetcode"的每个字符,同时对于每个字符,我们都会遍历从当前字符到字符串末尾的每个子字符串。 - 当 
i = 0时,我们检查子字符串"l", "le", "lee", "leet", "leetc", "leetco","leetcod", "leetcode"。当我们检查到"leet"时,我们发现"leet"在字典中,而且dp[0]是true,所以我们将dp[4]设置为true。 - 当 
i = 1时,我们检查子字符串"e", "ee", "eet", "eetc", "eetco", "eetcod", "eetcode"。但是因为dp[1]是false,所以我们不会更新任何dp[j]。 - 当 
i = 2和i = 3时,同样因为dp[2]和dp[3]都是false,所以我们也不会更新任何dp[j]。 - 当 
i = 4时,我们检查子字符串"c", "co", "cod", "code"。当我们检查到"code"时,我们发现"code"在字典中,而且dp[4]是true,所以我们将dp[8]设置为true。 - 最后,我们返回 
dp[8],也就是true,表示字符串"leetcode"可以被拆分为字典中的单词。 
4、复杂度分析
- 时间复杂度: O ( n 2 ) O(n^{2}) O(n2)。我们一共有 O ( n ) O(n) O(n) 个状态需要计算,每次计算需要枚举 O ( n ) O(n) O(n)个分割点,哈希表判断一个字符串是否出现在给定的字符串列表需要 O ( n ) O(n) O(n)的时间,因此总时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)。
 - 空间复杂度: O ( n ) O(n) O(n),哈希集合和dp布尔数组需要存放元素。
 
over,拜拜!


















