๐ ๋ฌธ์
- ๋ฌธ์์ด `s`, ๋จ์ด ์ฌ์ `wordDict`๊ฐ ์ฃผ์ด์ง
- wordDict์ ์๋ ๋จ์ด๋ค๋ก s๋ฅผ ๋ถํ ํ ์ ์๋์ง ํ์ธ (โ ๋จ์ด๋ค๋ก s๋ฅผ ๋ง๋ค ์ ์๋์ง ํ์ธ)
- wordDict๋ด์ ๋จ์ด๋ค์ ์ฌ๋ฌ๋ฒ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
์๊ฐ ํ๊ธฐ
40๋ถ ์ ๋ ๊ณ ๋ฏผํ๋ค๊ฐ ๋ต์ ๋ดค๋ค.
๋๋ ๋จ์ด ์ฌ์ ์ ์๋ ๋จ์ด๋ค์ ์ฒซ๊ธ์๋ฅผ key๋ก ํ์ฌ Map์ ์ ์ฅ ํ์ฌ ์ ๊ทผํ๋๋ก ํ๋ค.
์์) wordDict =[cats, sand, dog, and, cat]
Map: [a - and], [c - cat, cats], [d - dog ], [s- sand]
dfs๋ฅผ ์ด์ฉํ์ฌ ์ ๊ทผํ์ง๋ง, ์๊ฐ์ด๊ณผ์ ๊ฑธ๋ ค์ ํ๋ ธ๋ค. (โต ์ค๋ณต ํ์)
์ด ๋ฌธ์ ๋ฅผ ํ๊ธฐ ์ํด์ , ์ด์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํด ์ค๋ณต ํ์์ ํ์ง ์๋๋ก `memoization`์ ์ด์ฉํด์ผํ๋ค.
`DFS` ์ `DP`, ์ด ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ํ ์ ์๋ค.
๐ณ ์ ์ฒด ์์ค ์ฝ๋
class Solution {
static int maxlen;
public boolean wordBreak(String s, List<String> wordDict) {
Map<String, Boolean> map = new HashMap<>();
Set<String> wordSet = new HashSet<>(wordDict);
maxlen=0;
for(String word: wordDict) {
maxlen = Math.max(maxlen, word.length());
}
return dfs(s, map, wordSet);
}
public static boolean dfs(String s, Map<String, Boolean> memo, Set<String> wordSet) {
if(memo.containsKey(s)) return memo.get(s);
if(wordSet.contains(s)) return true;
for(int i=1;i<s.length();i++) {
String prefix = s.substring(0,i);
if(prefix.length()>maxlen){
break;
}
if(wordSet.contains(prefix) && dfs(s.substring(i), memo, wordSet)) {
memo.put(prefix, true);
return true;
}
}
memo.put(s,false);
return false;
}
}
โ ๋ถ๋ถ ์ฝ๋ ์ค๋ช
1. ๋ณ์ ์ ์ธ & ์ด๊ธฐํ
class Solution {
static int maxlen;
public boolean wordBreak(String s, List<String> wordDict) {
Map<String, Boolean> map = new HashMap<>();
Set<String> wordSet = new HashSet<>(wordDict);
maxlen=0;
for(String word: wordDict) {
maxlen = Math.max(maxlen, word.length());
}
return dfs(s, map, wordSet);
}
...
- `map`: ํ์ํ ๋ฌธ์์ด๊ณผ ๊ทธ ๊ฒฐ๊ณผ ์ ์ฅ
- `wordSet`: wordDict๋ฅผ set ์๋ฃ๊ตฌ์กฐ๋ก ์ ์ฅ
- `maxLen`: wordDict ๋ด ๊ฐ์ฅ ๊ธด ๋จ์ด ๊ธธ์ด ์ ์ฅ(๋ถํ์ํ ํ์ ๋ฐฉ์ง)
โ Set์ผ๋ก ๋ณ๊ฒฝํ์ฌ ํ์ํ๋ ์ด์
์ดํ dfs๋ฅผ ์งํํ๋ฉด์ `contains()` ๋ด์ฅ ํจ์๋ฅผ ์ฌ์ฉํ ์์
List์ Set ๋ชจ๋ ํด๋น ๋ด์ฅ ํจ์๋ฅผ ์ ๊ณตํ์ง๋ง, ์๊ฐ๋ณต์ก๋ ๋ฉด์์ ์ฐจ์ด๊ฐ ๋จ
`Set`์ ํ๊ท ์ ์ผ๋ก O(1)์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ง, `List`๋ O(N)์ ์๊ฐ๋ณต์ก๋๋ก Set์ด ๋ ํจ์จ์
๊ทธ ์ด์ ๋, Set์ ํด์ ํ ์ด๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ํ์์ ์งํํ๊ธฐ์, ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ ๋ ํด์๊ฐ์ ์ด์ฉํด ๋น ๋ฅด๊ฒ ์ฐพ์
๋ฐ๋ฉด์, List๋ ๋ฐฐ์ด์ด๋ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ก ๊ตฌํ๋๋ค.
๋ฐ๋ผ์ ๊ฐ ์์๋ฅผ ์์ฐจ์ ์ผ๋ก ๋น๊ตํ์ฌ ์ฐพ๊ธฐ ๋๋ฌธ์ ์ต์ ์ ๊ฒฝ์ฐ ๋ชจ๋ ์์๋ฅผ ๊ฒ์ฌํด์ผํ๋ฏ๋ก O(N)์ ์๊ฐ์ด ๊ฑธ๋ฆผ
2. DFS ์งํ
class Solution {
...
public static boolean dfs(String s, Map<String, Boolean> memo, Set<String> wordSet) {
if(memo.containsKey(s)) return memo.get(s);
if(wordSet.contains(s)) return true;
for(int i=1;i<s.length();i++) {
String prefix = s.substring(0,i);
if(prefix.length()>maxlen){
break;
}
if(wordSet.contains(prefix) && dfs(s.substring(i), memo, wordSet)) {
memo.put(prefix, true);
return true;
}
}
memo.put(s,false);
return false;
}
}
1-1. ์ด๋ฏธ ํ์ํ ๋ฌธ์์ด์ธ ๊ฒฝ์ฐ (`memo.conatinsKey`) ํด๋น ๋ฌธ์์ด์ ํ์ ๊ฒฐ๊ณผ ๋ฐํ
1-2. wordSet์ ํ์ฌ ๋ฌธ์์ด `s`๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ true ๋ฐํ
2. ์ฃผ์ด์ง ๋ฌธ์์ด `s`์ ์ฒ์๋ถํฐ ํ ๊ธ์์ฉ ๋๋ ค๊ฐ๋ฉด์ ๋ถ๋ถ ๋ฌธ์์ด์ `prefix`์ ์ ์ฅ
3. ๋ง์ผ, prefix์ ๊ธธ์ด๊ฐ max_len๋ณด๋ค ๊ธด ๊ฒฝ์ฐ, ํ์ํ์ง์์
โต ๋จ์ด ์ฌ์ ์ ์๋ ๋จ์ด๋ก๋ง ๋ฌธ์์ด์ ๋ถํดํจ
prefix ๊ธธ์ด๊ฐ ๋จ์ด ์ฌ์ ๋ด ์ต์ฅ ๊ธธ์ด์ ๋จ์ด๋ณด๋ค ๊ธด ๊ฒฝ์ฐ, ํ์ํ ํ์ ์์ (์ด์ฐจํผ ๋จ์ด ์ฌ์ ์ ์์)
4. ๋จ์ด ์ฌ์ ์ prefix๊ฐ ์กด์ฌํ๊ณ (๋ถํด ๊ฐ๋ฅ), ๋ถํ ์ดํ ๋ฌธ์์ด ๋ํ ์กด์ฌํ๋ ๊ฒฝ์ฐ return true
4๋ฒ ๋ก์ง์ด ์ฌ๊ท๋ก ์ด๋ฃจ์ด์ง๋ค ๋ณด๋ ์ด๋ป๊ฒ ๋์ํ๋์ง ํ ๋์ ํ์
ํ๊ธฐ ์ด๋ ต๋ค.
์๋์ ๊ทธ๋ฆผ์ ํตํด ์ฌ๊ท ํ๋ฆ์ ์ค๋ช
ํ๊ฒ ๋ค.
โจ ๊ฒฐ๊ณผ
์๋๋ DP๋ฅผ ํ์ฉํด ํธ๋ ๋ฐฉ์์ด๋ค.
dfs๋ณด๋ค ํจ์จ์ ์ด๋, dfs์์ maxLen์ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ๋น์ทํ ์ฑ๋ฅ์ ๋ณด์๋ค.
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
boolean []dp = new boolean[s.length()+1];
dp[0] = true;
int max_len = 0;
for(String word : wordDict) {
max_len = Math.max(word.length(), max_len);
}
for(int i=1;i<=s.length();i++){
for(int j =i-1;j>=Math.max(i-max_len-1, 0);j--){
String check = s.substring(j,i);
if(dp[j]&&wordDict.contains(check)){
dp[i] = true;
break;
}
}
}
System.out.println(dp[s.length()]);
return dp[s.length()];
}
}