Word Break
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"
.
-----------------------------------------------------------------------
Just DP
dp[i] has the boolean value that means if string[i : n] can be partitioned according to our dictionary. Hence dp[len] represents the empty string and dp[0] is the answer we are looking for.
For each iteration in the inner for loop, we add a new cut at index j to string[i : n], in whcih string[i : j] has never checked before but string[j + 1 : n](result is in dp[j + 1]) has been known since the previous iteration in outer loop.
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int len = s.length();
vector<bool> dp(len + 1,false);
dp[len] = true;
for (int i = len - 1; i >= 0; i--) {
for (int j = i; j < len; j++) {
string str = s.substr(i,j - i + 1);
if (dict.find(str) != dict.end() && dp[j + 1]) {
dp[i] = true;
break;
}
}
}
return dp[0];
}
};
Java, memoization. Updated on Jun-25th-2018
class Solution {
public boolean wordBreak(String s, List wordDict) {
Map m = new HashMap<>();
return dfs(s, new HashSet(wordDict), m);
}
private boolean dfs(String s, Set dic, Map m) {
if (s.length() == 0) return true;
for (int i = 0; i < s.length(); i++) {
String sub = s.substring(0, i + 1);
String nextSub = s.substring(i + 1);
if (!dic.contains(sub)) {
continue;
}
boolean next;
if (m.containsKey(nextSub)) {
next = m.get(nextSub);
}else {
next = dfs(s.substring(i + 1), dic, m);
}
if (next) return true;
}
m.put(s, false);
return false;
}
}
ToDo: 有意思的bfs,把每个单词当作是node,queue里可以存index
https://leetcode.com/problems/word-break/discuss/43797/A-solution-using-BFS
Word Break II
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"]
.
-----------------------------------------------
Based on Word Break, add one more DP to store all possible partition at current index
因为LC加了新的test case,以下代码得加一段word break I的代码,来先检测s是否能被分解
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int len = s.length();
vector<bool> dp(len + 1,false);
vector<vector<string> > dp2(len + 1,vector<string>());
dp2[len].push_back("");
dp[len] = true;
for (int i = len - 1; i >= 0; i--) {
for (int j = i; j < len; j++) {
string str = s.substr(i,j - i + 1);
if (dict.find(str) != dict.end() && dp[j + 1]) {
dp[i] = true;
for (int index = 0; index < dp2[j + 1].size(); index++) {
string empty = "";
if (j + 1 != len) empty = " ";
string n = str + empty + dp2[j + 1][index];
dp2[i].push_back(n);
}
}
}
}
return dp2[0];
}
};
dfs,减枝之后也能过OJ
class Solution {
public:
void dfs(vector<string> &rt, string s, int index,string cur, unordered_set<string>& wordDict) {
if (index == s.length()) {
rt.push_back(cur);
return;
}
bool notFound = true;
for (int i = s.size() - 1; i >= index; --i) {
if (wordDict.find(s.substr(i)) != wordDict.end()) {
notFound = false;
break;
}
}
if (notFound) { return ; }
for (int i = index; i < s.length(); i++) {
string sub = s.substr(index,i - index + 1);
if (wordDict.find(sub) != wordDict.end()) {
string t = cur;
if (t.length() == 0) {
t = sub;
}else {
t += " " + sub;
}
dfs(rt,s,i + 1,t,wordDict);
}
}
}
vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
vector<string> rt;
dfs(rt,s,0,"",wordDict);
return rt;
}
};
Java,在Word Break I的基础上进行修改的dfs. Updated on Jun-26th-2018
class Solution {
public List wordBreak(String s, List wordDict) {
return dfs(s, new HashSet(wordDict), new HashMap>());
}
private List dfs(String s, Set dic, Map> m) {
if (s.length() == 0) return new ArrayList<>();
List rt = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
String sub = s.substring(0, i + 1);
String nextSub = s.substring(i + 1);
if (!dic.contains(sub)) {
continue;
}
List next;
if (m.containsKey(nextSub)) {
next = m.get(nextSub);
}else {
next = dfs(s.substring(i + 1), dic, m);
}
for (String can : next) {
rt.add(sub + " " + can);
}
if (i == s.length() - 1) {
rt.add(sub);
}
}
m.put(s, rt);
return rt;
}
}
Todo: 写一个iterate版本的
Linked List Cycle
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
--------------------------------------------------------------
two pointers, one traverses twice as fast as the other
return true if they meet
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if (head == NULL) return false;
ListNode *slow = head, *fast = head->next;
bool flag = false;
while (fast != NULL) {
if (fast == slow) {
flag = true;
break;
}
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
}
return flag;
}
};
Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return
null
.
Follow up:
Can you solve it without using extra space?
-----------------------------------------------------------------
Floyd's cycle-finding algorithm
Note: as opposed to Linked List Cycle
1) fast is initialized to head, not head->next
2) if (fast == slow) is executed after pointers've been moved
Update Dec-30th-2014
假设 x 为起跑线到loop的起点的距离,y为该起点到两个指针相遇点的距离,z为该点到起点的距离,则loop的长度 L = y + z
m 为慢指针在相遇时跑过的距离: m = x + y
n 为快指针在相遇时跑过的距离: n = x + y + k * L, k > 0
已知 2m = n
2(x + y) = x + y + k * L
x = k * L - y
x = (k - 1) * L + z
证毕
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (head == NULL) return false;
ListNode *slow = head, *fast = head;
bool flag = false;
while (fast != NULL) {
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
if (fast == slow) {
flag = true;
break;
}
}
if (!flag) return NULL;
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
};