算法BFS--单词拆分

https://leetcode-cn.com/problems/word-break/

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:拆分时可以重复使用字典中的单词。你可以假设字典中没有重复的单词。

可以采用DFS BFS或者DP来解决  无论采用何种方式,都类似于一种搜索问题。

依次遍历给定字符串的每一个字符串 假定当前遍历位置序号为i,则字符串S此时可以分为两部分s0=s[0, i-1], s1=s[i, s.length] 此时如果满足s0在给定的单词列表中并且s1可以递归继续拆分(s1是S的一个子问题),则S可以被正确拆分。

1.DFS

从字符串0位置出发,依次遍历从0开始的每个位置i,此时s切割为s0, s1  判断s0是否在单词列表中,如果在,递归判断s1是否可以拆解

public boolean wordBreak2(String s, List wordDict) {
        Set set = new HashSet<>(wordDict);
        return dfs2(s, 0, s.length()-1, set);
    }

    private boolean dfs2(String s, int start, int length, Set set) {
        if (start > length) return true;
        for (int i=start+1; i<=length+1; i++) {
            String prex = s.substring(start, i);
            System.out.println(prex+" " + i + " " + length);
            if (set.contains(prex) && dfs2(s, i, length, set)) {
                return true;
            }
        }
        return false;
    }

优化一下,判断s1子问题时,对于s1来说,需要从起始位置start 再次拆分, 可以记录之前start位置的记录结果,如果已经计算直接返回,避免重复计算

// DFS+记忆化
    public boolean wordBreak3(String s, List wordDict) {
        Set set = new HashSet<>(wordDict);
        Boolean[] flag = new Boolean[s.length()+1];
        return dfs3(s, 0, s.length()-1, set, flag);
    }

    private boolean dfs3(String s, int start, int length, Set set, Boolean[] flag) {
        if (start > length) return true;
        if (flag[start] != null) return flag[start];
        for (int i=start+1; i<=length+1; i++) {
            String prex = s.substring(start, i);
            if (set.contains(prex) && dfs3(s, i, length, set, flag)) {
                flag[start] = true;
                return true;
            }
        }
        flag[start] = false;
        return false;
    }

2.BFS

从0位置触发 依次遍历每一个位置i 此时字符串被拆分成两个部分s0, s1 如果s0在单词列表中,说明i可能是一种可行的拆分方式,观察i的位置  如果i是字符串结尾 则直接返回true 表示已经正确拆分,如果不是则将i放入队列中,等待从i位置开始处理下一个子问题。

public boolean wordBreak4(String s, List wordDict) {
        Set set = new HashSet<>(wordDict);
        Queue queue = new LinkedList<>();
        queue.add(0);
        while (!queue.isEmpty()) {
            int start = queue.poll();
            for (int i=start+1; i<=s.length(); i++) {
                String prex = s.substring(start, i);
                System.out.println(prex+" " + i + " " + start);
                if (set.contains(prex)) {
                    if (i

优化,记录已经访问过的问题

 // BFS优化
    public boolean wordBreak5(String s, List wordDict) {
        Set set = new HashSet<>(wordDict);
        boolean[] flag = new boolean[s.length()+1];
        Queue queue = new LinkedList<>();
        queue.add(0);
        while (!queue.isEmpty()) {
            int start = queue.poll();
            if (flag[start]) continue;
            flag[start] = true;
            for (int i=start+1; i<=s.length(); i++) {
                String prex = s.substring(start, i);
                System.out.println(prex+" " + i + " " + start);
                if (set.contains(prex)) {
                    if (i

3.DP

https://leetcode-cn.com/problems/word-break/solution/dan-ci-chai-fen-by-leetcode-solution/

算法BFS--单词拆分_第1张图片

// DP
    public boolean wordBreak1(String s, List wordDict) {
        Set set = new HashSet<>(wordDict);
        boolean[] dp = new boolean[s.length()+1];
        dp[0] = true;
        for (int i=1; i<=s.length(); i++) {
            for (int j=0; j

你可能感兴趣的:(算法与数据结构,leetcode)