算法训练营day46

一、单词拆分

元素无重可复选

  1. base case i==s.length return true,遍历到了最后,
    1. 因为i+len = s.length,len初始值为1,那么i+1 = s.length,那么i = s.lenth -1 也就是最后一个字符位置
  2. dp(s,i)函数定义:返回 si... 是否能够被拼出
  3. 判断字符串S的前缀0,k是否存在于WordDict,存在就递归dp(s, i+len)
java 复制代码
class Solution {
    // 用哈希集合方便快速判断是否存在
    HashSet<String> wordDict;
    // 备忘录,-1 代表未计算,0 代表无法凑出,1 代表可以凑出
    int[] memo;

    // 主函数
    public boolean wordBreak(String s, List<String> wordDict) {
        // 转化为哈希集合,快速判断元素是否存在
        this.wordDict = new HashSet<>(wordDict);
        // 备忘录初始化为 -1
        this.memo = new int[s.length()];
        Arrays.fill(memo, -1);
        return dp(s, 0);
    }

    // 定义:s[i..] 是否能够被拼出
    boolean dp(String s, int i) {
        // base case
        if (i == s.length()) {
            return true;
        }
        // 防止冗余计算
        if (memo[i] != -1) {
            return memo[i] == 0 ? false : true;
        }

        // 遍历 s[i..] 的所有前缀
        for (int len = 1; i + len <= s.length(); len++) {
            // 看看哪些前缀存在 wordDict 中
            String prefix = s.substring(i, i + len);
            if (wordDict.contains(prefix)) {
                // 找到一个单词匹配 s[i..i+len)
                // 只要 s[i+len..] 可以被拼出,s[i..] 就能被拼出
                boolean subProblem = dp(s, i + len);
                if (subProblem == true) {
                    memo[i] = 1;
                    return true;
                }
            }
        }
        // s[i..] 无法被拼出
        memo[i] = 0;
        return false;
    }
}
二、单词拆分2
java 复制代码
class Solution {
    HashSet<String> wordDict;
    // 备忘录
    List<String>[] memo;

    public List<String> wordBreak(String s, List<String> wordDict) {
        this.wordDict = new HashSet<>(wordDict);
        memo = new List[s.length()];
        return dp(s, 0);
    }



    // 定义:返回用 wordDict 构成 s[i..] 的所有可能
    List<String> dp(String s, int i) {
        List<String> res = new LinkedList<>();
        if (i == s.length()) {
            res.add("");
            return res;
        }
        // 防止冗余计算
        if (memo[i] != null) {
            return memo[i];
        }
        
        // 遍历 s[i..] 的所有前缀
        for (int len = 1; i + len <= s.length(); len++) {
            // 看看哪些前缀存在 wordDict 中
            String prefix = s.substring(i, i + len);
            if (wordDict.contains(prefix)) {
                // 找到一个单词匹配 s[i..i+len)
                List<String> subProblem = dp(s, i + len);
                // 构成 s[i+len..] 的所有组合加上 prefix 
                // 就是构成构成 s[i] 的所有组合
                for (String sub : subProblem) {
                    if (sub.isEmpty()) {
                        // 防止多余的空格
                        res.add(prefix);
                    } else {
                        res.add(prefix + " " + sub);
                    }
                }
            }
        }
        // 存入备忘录
        memo[i] = res;
        
        return res;
    }
}
相关推荐
Nebula_g6 小时前
JavaSE基础语法:面向对象高级(代码中的成分)
java·开发语言·编程·javase·技术栈·高级语法
AC赳赳老秦7 小时前
公开图片 OCR 数据提取:OpenClaw 合规采集公开信息图,识别文字与表格并转化为结构化数据
java·大数据·前端·数据库·python·php·openclaw
小强库计算机毕业设计8 小时前
SpringBoot+Vue3 学生宿舍管理系统实战
java·spring boot·后端·vue·学生宿舍管理系统
李冰然8 小时前
深入Java集合框架:HashMap源码解析(JDK 8)
java
人道领域9 小时前
【0-1的agent进阶篇】RAG:从Embedding到检索增强生成的底层逻辑
java·embedding·agent·rag
桦说编程10 小时前
盘点并发集合里那些容易误判的行为
java·后端·性能优化
IT爱学堂11 小时前
java版数据结构和算法+AI算法和技能学习指南
java·开发语言
evans在进步11 小时前
LeetCode 394:字符串解码——Java 单栈模拟与嵌套解析详解
java·python·leetcode
AI人工智能+电脑小能手12 小时前
大白话说Java设计模式-17-装饰器模式(源码剖析篇)
java·spring·设计模式·装饰器模式·源码分析·io流
-dzk-12 小时前
【动态规划】LC 118.杨辉三角
算法·动态规划