Leetcode 139 Word Break

Leetcode 139 Word Break

题目

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

Note:
The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.

Example 1:
Input: s = “leetcode”, wordDict = [“leet”, “code”]
Output: true
Explanation: Return true because “leetcode” can be segmented as “leet code”.

Example 2:
Input: s = “applepenapple”, wordDict = [“apple”, “pen”]
Output: true
Explanation: Return true because “applepenapple” can be segmented as “apple pen apple”.
Note that you are allowed to reuse a dictionary word.

Example 3:
Input: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
Output: false

思路和代码

就考虑直接从前往后匹配了开始搜子串了,然后全部都是a的test case又没有过,hashset存了结果也没有过。

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        if (s == null || s.length() == 0) {
            return false;
        }
        return helper(s, wordDict, new HashSet<>(), 0);

    }
    public boolean helper(String s, List<String> wordDict, HashSet<String> set, int index) {
        if (index == s.length()) return true;
        if (set.contains(s.substring(index, s.length()))) return true;
        if (index!= 0) set.add(s.substring(0, index));
        for (String temp : new HashSet<>(set)) {
            if (s.startsWith(temp, index)) {
                if (helper(s, wordDict, set, index + temp.length())) {
                    return true;
                }
            }
        }
        for (String temp : wordDict) {
            if (s.startsWith(temp, index)) {
                if (helper(s, wordDict, set, index + temp.length())) {
                    return true;
                }
            }
        }
        return false;
    }
}

参考了Sample 0s的答案,发现思路基本一样但是这个很快,然后打断点进去看了一下。发现自己存东西的时候思路有误,按照题目要求是有一个成立就直接返回了,所以存这些“正确”值并没有太大的用处,应该是需要做到“不正确”的时候提前返回,不要全部遍历。

下面代码的思路是在第一次进入canReallyBreak函数的时候,就改变memo值,meno[index]=false代表s从index到结尾不能被表示,这样如果中间或结尾有一段不包含在dict内的,那么后面的memo全部是false,每次遍历s到这里就因为不正确而停止了,相当于缩短了s的长度。

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        boolean canBreak = false;
        
        boolean memo[] = new boolean[s.length()];
        Arrays.fill(memo, true);
        
        for(String word : wordDict) {
            if(s.startsWith(word, 0)) {
                // System.out.println("Picking word: "+word);
                canBreak = canReallyBreak(s, wordDict, word.length(), memo);
                if(canBreak) break;
            }
        }
        
        return canBreak;
    }
    
    public boolean canReallyBreak(String s, List<String> wordDict, int index, boolean[] memo) {
        // System.out.println("At index: "+index);
        if(index >= s.length()) return true;
        
        if(!memo[index]) return false;

        boolean canBreak = false;
        
        for(String word : wordDict) {
            if(s.startsWith(word, index)) {
                // System.out.println("Picking word: "+word);
                canBreak = canReallyBreak(s, wordDict, index + word.length(), memo);
                if(canBreak) break;

            }
        }
        memo[index] = canBreak;
        
        return canBreak;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值