LeetCode 139: Word Break

LeetCode 139: Word Break

    • [1. 📌 Problem Links](#1. 📌 Problem Links)
    • [2. 🧠 Solution Overview](#2. 🧠 Solution Overview)
    • [3. 🟢 Solution 1: Dynamic Programming (Bottom-Up)](#3. 🟢 Solution 1: Dynamic Programming (Bottom-Up))
      • [3.1. Algorithm Idea](#3.1. Algorithm Idea)
      • [3.2. Key Points](#3.2. Key Points)
      • [3.3. Java Implementation](#3.3. Java Implementation)
      • [3.4. Complexity Analysis](#3.4. Complexity Analysis)
    • [4. 🟡 Solution 2: Optimized DP with Length Pruning](#4. 🟡 Solution 2: Optimized DP with Length Pruning)
      • [4.1. Algorithm Idea](#4.1. Algorithm Idea)
      • [4.2. Key Points](#4.2. Key Points)
      • [4.3. Java Implementation](#4.3. Java Implementation)
      • [4.4. Complexity Analysis](#4.4. Complexity Analysis)
    • [5. 🔵 Solution 3: BFS with Visited Tracking](#5. 🔵 Solution 3: BFS with Visited Tracking)
      • [5.1. Algorithm Idea](#5.1. Algorithm Idea)
      • [5.2. Key Points](#5.2. Key Points)
      • [5.3. Java Implementation](#5.3. Java Implementation)
      • [5.4. Complexity Analysis](#5.4. Complexity Analysis)
    • [6. 📊 Solution Comparison](#6. 📊 Solution Comparison)
    • [7. 💡 Summary](#7. 💡 Summary)

2. 🧠 Solution Overview

This problem requires determining if a string s can be segmented into a space-separated sequence of one or more dictionary words from wordDict. The same word may be reused multiple times. Below are the main approaches:

Method Key Idea Time Complexity Space Complexity
Dynamic Programming DP array storing segmentability for each position O(n²) O(n)
BFS with Pruning Treat as graph traversal with visited optimization O(n²) O(n)
Optimized DP with Length Pruning DP with max word length optimization O(n×L) O(n)

3. 🟢 Solution 1: Dynamic Programming (Bottom-Up)

3.1. Algorithm Idea

We use a DP array where dp[i] represents whether the substring s[0...i-1] (the first i characters) can be segmented into dictionary words. The key insight is that if we can segment the substring ending at position j, and the substring from j to i is in the dictionary, then we can also segment the substring ending at position i.

3.2. Key Points

  • State Definition : dp[i] = whether first i characters can be segmented
  • State Transition : dp[i] = true if there exists j where dp[j] == true and s[j...i-1] is in wordDict
  • Initialization :
    • dp[0] = true (empty string can always be segmented)
    • All other dp[i] initialized to false
  • Processing Order: Process positions from 1 to n sequentially

3.3. Java Implementation

java 复制代码
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        if (s == null || s.length() == 0) return false;
        
        Set<String> dict = new HashSet<>(wordDict);
        int n = s.length();
        boolean[] dp = new boolean[n + 1];
        dp[0] = true; // Base case: empty string
        
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < i; j++) {
                // If prefix [0,j) is segmentable and substring [j,i) is in dictionary
                if (dp[j] && dict.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break; // No need to check other j's for this i
                }
            }
        }
        
        return dp[n];
    }
}

3.4. Complexity Analysis

  • Time Complexity : O(n²) - Two nested loops over string length
  • Space Complexity : O(n) - For DP array and dictionary set

4. 🟡 Solution 2: Optimized DP with Length Pruning

4.1. Algorithm Idea

This approach optimizes the standard DP solution by using the maximum word length from the dictionary to limit the inner loop range. This avoids unnecessary checks when the potential word length exceeds the maximum available dictionary word length.

4.2. Key Points

  • Length Pruning : Calculate maxLen - the longest word in dictionary
  • Optimized Inner Loop : Only check substrings with length ≤ maxLen
  • Reverse Iteration: Check from the end of potential words for better performance

4.3. Java Implementation

java 复制代码
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        if (s == null || s.length() == 0) return false;
        
        Set<String> dict = new HashSet<>(wordDict);
        int n = s.length();
        
        // Calculate maximum word length for pruning
        int maxLen = 0;
        for (String word : dict) {
            maxLen = Math.max(maxLen, word.length());
        }
        
        boolean[] dp = new boolean[n + 1];
        dp[0] = true;
        
        for (int i = 1; i <= n; i++) {
            // Only check back up to maxLen characters
            int start = Math.max(0, i - maxLen);
            for (int j = i - 1; j >= start; j--) {
                if (dp[j] && dict.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        
        return dp[n];
    }
}

4.4. Complexity Analysis

  • Time Complexity : O(n×L) - Where L is maxLen, typically much smaller than n
  • Space Complexity : O(n) - Same as standard DP

5. 🔵 Solution 3: BFS with Visited Tracking

5.1. Algorithm Idea

We can model this as a graph search problem where each position represents a node, and we traverse from each position to all reachable positions using dictionary words. BFS naturally finds the shortest path to the end, and we use a visited array to avoid reprocessing the same states.

5.2. Key Points

  • State Representation: Current position in the string
  • Graph Traversal: From each position, try all possible dictionary words
  • Visited Tracking: Avoid revisiting the same positions
  • Termination: Return true when we reach the end of the string

5.3. Java Implementation

java 复制代码
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        if (s == null || s.length() == 0) return false;
        
        Set<String> dict = new HashSet<>(wordDict);
        int n = s.length();
        
        // Calculate maximum word length for pruning
        int maxLen = 0;
        for (String word : dict) {
            maxLen = Math.max(maxLen, word.length());
        }
        
        Queue<Integer> queue = new LinkedList<>();
        boolean[] visited = new boolean[n + 1];
        queue.offer(0);
        visited[0] = true;
        
        while (!queue.isEmpty()) {
            int start = queue.poll();
            
            // Try all possible end positions
            for (int end = start + 1; end <= n && end - start <= maxLen; end++) {
                if (!visited[end] && dict.contains(s.substring(start, end))) {
                    if (end == n) {
                        return true; // Reached the end
                    }
                    queue.offer(end);
                    visited[end] = true;
                }
            }
        }
        
        return false;
    }
}

5.4. Complexity Analysis

  • Time Complexity : O(n²) - Each position processed once, with up to n checks
  • Space Complexity : O(n) - For queue and visited array

6. 📊 Solution Comparison

Solution Time Space Pros Cons
Standard DP O(n²) O(n) Most intuitive, guaranteed optimal Slower for long strings
Optimized DP O(n×L) O(n) Much faster with length pruning Slightly more complex
BFS Approach O(n²) O(n) Natural graph interpretation May explore unnecessary states

7. 💡 Summary

For the Word Break problem:

  • Learning & Understanding : Start with Standard DP to grasp the fundamental state transition concept
  • Interviews & Practical Use : Optimized DP with Length Pruning offers the best performance for most scenarios
  • Alternative Perspective : BFS Approach provides a different intuition about the problem as a reachability graph

The key insight is recognizing the optimal substructure - the segmentability of a string depends on the segmentability of its prefixes and the presence of the remaining suffix in the dictionary.

Just as words give meaning to random letters, the Word Break problem teaches us that complex challenges can be solved by breaking them into smaller, recognizable patterns and systematically combining their solutions.

相关推荐
MartinYeung58 分钟前
[论文学习]DP2Unlearning:高效且具保证的大型语言模型遗忘框架(基于差分隐私的 LLM Unlearning 方法)
学习·算法·语言模型
Tian_Hang21 分钟前
C++原型模式(Protype)
开发语言·c++·算法
bIo7lyA8v21 分钟前
算法复杂度的渐进分析与实际运行时间的差异的技术8
算法
JAVA面经实录9171 小时前
操作系统(面试全覆盖)
java·计算机网络·面试
编程的一拳超人1 小时前
Maven 国内高速镜像推荐(按速度排序)
java·maven
yuan199971 小时前
欧拉梁静力与屈曲计算的 MATLAB 实现(有限差分法 + 解析解)
开发语言·算法·matlab
云烟成雨TD2 小时前
Spring AI 1.x 系列【61】Spring AI 2.0 升级指南
java·人工智能·spring
汉克老师2 小时前
GESP7级C++考试语法知识(二、指数函数(3、综合练习)
c++·算法·数学建模·指数函数·gesp7级·复利
lulu12165440782 小时前
OpenRouter Fusion 多模型融合架构深度拆解:预算级模型组团打平 Fable 5,多模型协作才是 AGI 的正确打开方式?
java·人工智能·架构·ai编程·agi