leetcode 140:Word Break II 采用很巧妙的动态规划和DFS联合使用 JAVA源代码实现

本文深入探讨了如何利用字典匹配和动态规划优化技术,解决构建符合字典规则的句子问题。通过分析三种不同的思路,最终实现了一个高效的算法来生成所有可能的句子组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

Return all such possible sentences.

For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].

A solution is ["cats and dog", "cat sand dog"].

1.思路1

第一个想法就是跟word break一样,直接DFS暴力检索,不出所料,TML了

2.思路2

暴力检索肯定不行,那么就优化。想到能否使用动态规划,首先搜索一下那些字符串是包含在dict中,形成一个动态规划的数组,去掉一些无用的搜索,然而依旧TML

3.思路3

1.既然想到动态规划剪枝了,再多想以下,我们不只是需要考虑当前子串在字典中,还要考虑当前子串之前的字符串也在字典中,这样将大大减少搜索路径。
2.我们查找是否包含在字典中是从前往后找的,那么我们找相关路径的时候反向遍历将会大大减少搜索路径。
实现了以上两点就已经大大优化了我们的检索。
具体实现代码如下:
List<String> result;
    public List<String> wordBreak(String s, Set<String> wordDict) {
        result = new ArrayList<String>();
        int n = s.length();
        //对每一个i都形成一个可以跳跃的点
        List<Integer>[] pointer = new List[n];
        for(int i=0;i<n;i++) pointer[i]=new ArrayList<Integer>();
        //动态规划形成跳跃点
        for(int i=0;i<n;i++){
            for(int j=0;j<=i;j++){
            	//递归的保证j-1可以形成单词,大大地剪枝
                if(wordDict.contains(s.substring(j,i+1))&&(j==0||pointer[j-1].size()>0))
                    pointer[i].add(j);
            }
        }
        //从后往前的递归
        helper(pointer, s, n-1, "");
        return result;
    }
    //DFS
    public void helper(List<Integer>[] pointer, String s, int i, String pattern){
        if(i<0){
            result.add(pattern);
            return;
        }
        for(Integer item:pointer[i]){
            String nextPattern = pattern.length()==0?s.substring(item,i+1):s.substring(item,i+1)+" "+pattern;
            helper(pointer, s, item-1, nextPattern);
        }
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值