Leetcode - Word Break

**
Question:

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

For example, given
s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".
**

My code:

import java.util.Set;

public class Solution {
    public boolean wordBreak(String s, Set wordDict) {
        boolean[] isBreakUp = new boolean[s.length() + 1];
        isBreakUp[0] = true;
        for (int i = 1; i < s.length() + 1; i++) {
            for (int j = 0; j < i; j++) {
                if (isBreakUp[j] && wordDict.contains(s.substring(j, i)))
                    isBreakUp[i] = true;
            }
        }
        return isBreakUp[s.length()];
    }
}

My test result:

Leetcode - Word Break_第1张图片
Paste_Image.png

这次作业是挺带劲的。因为我没有做出来。。后来一查,恩,是Medium。那就不难过啦。
说实话,这次作业还是做出来的。但是用的递归,用时过长了,就测试不出来了。
然后我就看了网上大神写的代码。没话说。怎么总结呢?总结不出来。这就是一种想法。按我说,就是步步为营,并且,同时,保证不会重复判断之前已经判断过的情况。我看了网上评论,说这东西就是 dynamic programming. 实在太累了。明天回来一定好好查下,然后总结到这里。

然后,展示下我自己写的递归版代码:

public class Solution {
    public boolean wordBreak(String s, Set wordDict) {
        return this.isBreakUp(s, wordDict, 0, s.length());
    }
    
    private boolean isBreakUp(String s, Set wordDict, int head, int length) {
        if (head == length)
            return true;
        for (int i = head; i < s.length(); i++) {
            if (wordDict.contains(s.substring(head, i + 1)))
                if (isBreakUp(s.substring(i + 1, s.length()), wordDict, i + 1, length))
                    return true;
                else
                    continue;
            else
                continue;
        }
        return false;
    }
}

这个递归我觉得写得还是挺不错的。为什么会超时呢?很明显,因为有很多情况,我之前已经判断过了,之后会继续重复判断。所以必须要设标志位来避免重复判断。

**
总结:
Dynamic Programming:网上又叫做,动态规划。我不是很理解。明天上网查了再说。
**

说好的一天至少一道题目。今天别看我现在凌晨2:43才提交。其实23:30就写好了。
今天早上就去了学校复习。然后对C++有了更深层次的理解。
这个也是明天必须得总结的。如何用C来实现面向对象编程。其实C中就含有向上转型和向下转型的特点,就是结构体指针和void指针的配合。
然后,我也终于明白了模板和继承是完全不同的。比如,模板是静态的,是编译时候完成的。而继承是动态的,是运行时候动态绑定的。明天总结。
一个小疑问,如果谁正好看到了这篇文章,又正好懂,万望求教。
**
Java中是不是只有继承,没有模板这种概念?模板是不是函数编程特有的概念?
**

C++复习剩下的就是一块自己一直很懂的地方,函数式编程。
所以明天也得查一下什么叫做函数编程,还有 λ-expression.
然后今天学习了电气上面的一些知识。觉得好牛逼。。。power application 原来也已经和计算机紧密结合到这个地步了。
单相不可控整流器
三相不可控整流器
单相可控整流器
三相可控整流器
overlap现象。。。。
这些就不总结了。感觉还是挺牛逼的。
明天总结下,
动态规划,函数编程,模板和继承,C实现面向对象。

累死了累死了。回来写代码到23:30,又接着写报告到现在。每次交报告,都是看出人性劣根性的最好机会。有些人就想混,比如我。有些人就是不肯给。有些人不肯给但又不想直接表现出来,就会采取各种方式搪塞过去。
Anyway, Good luck, Richardo!

My code:

public class Solution {
    public boolean wordBreak(String s, Set wordDict) {
        if (wordDict.contains(s)) {
            return true;
        }
        int n = s.length();
        boolean[] flag = new boolean[n + 1];
        flag[0] = true;
        for (int i = 1; i < n + 1; i++) {
            for (int j = 0; j < i; j++) {
                if (flag[j] && wordDict.contains(s.substring(j, i))) {
                    flag[i] = true;
                    break;
                }
            }
        }
        
        return flag[n];
    }
}

这个是DP的解法。复杂度是 O(n ^ 2)

然后发现还有种解法是 BFS

My code:

public class Solution {
    public boolean wordBreak(String s, Set wordDict) {
        if (wordDict.contains(s)) {
            return true;
        }
        int n = s.length();
        Queue q = new LinkedList();
        Set isVisited = new HashSet();
        q.offer(0);
        while (!q.isEmpty()) {
            int currIndex = q.poll();
            for (int i = currIndex + 1; i <= s.length(); i++) {
                if (isVisited.contains(i)) {
                    continue;
                }
                else if (wordDict.contains(s.substring(currIndex, i))) {
                    if (i == s.length()) {
                        return true;
                    }
                    else {
                        q.offer(i);
                        isVisited.add(i);
                    }
                }
            }
        }
        
        return false;
    }
}

reference:
https://discuss.leetcode.com/topic/2545/a-solution-using-bfs/5

每个节点都是在string s 中的 position, 边是 dictionary 里面的string
如果position0 + word1 --> position5
那么就是两个结点,0 and 5,中间有一条边,就是这个word

这道题目让我想起了另外一道题目: Jump game
但是不同。
那道题目, nums[i] + i 是下一步可以达到的最大位置,但是在这个位置之前的位置,也都是可以达到的。
而这道题目,在这之前的位置,并不能达到。
所以这道题目可以用BFS来解,而Jump game 不行。

另外,对已经确定可以达到的结点,把他们放入set中,这样以后就不会重复加入到队列里面去导致重复访问了。

Anyway, Good luck, Richardo! -- 09/05/2016

你可能感兴趣的:(Leetcode - Word Break)