Word Break - LeetCode
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
- 문제 내용 : 주어진 문자열을 주어진 문자의 그룹으로 표현이 가능한가?
- 접근 방법
모든 경우의 수를 처리한다
s = "leetcode", wordDict = ["leet","leets", "code"]
가 주어졌다고 했을때
leet와 code로 구성되어있는지 확인 하는 방법이 있고,
leets와 ode로 구성되어있는 확인 하는 방법이 있다.
하지만 이 방법은 다소 문제가 있다.
만약에 아래와 같이 주어진 문제가 있다고 생각해 보자.
s = "aaaaaaaaaa", wordDict = ["a","aa", "aaa"]
a와 aaaaaaaaa로 이루어진 경우의 수
aa와 aaaaaaaa로 이루어진 경우의 수
aaa와 aaaaaaa로 이루어진 경우의 수가 생긴다.
여기서 다시 한번
aaaaaaaaa는
a와 aaaaaaaa로 이루어진 경우의 수
aa와 aaaaaaa로 이루어진 경우의 수
aaa와 aaaaaa로 이루어진 경우의 수가 생긴다.
즉 최대 N개의 wordDict가 있다고 하면 S의 길이가 길때 N^N의 횟수로 처리 범위가 엄청나게 늘어나게 된다.
위의 짧은 예봐 봐도 3가지 경우의 수에 다시 3가지 경우의 수 3 * 3이 생긴 것을 확인 할 수 있다.
이를 지속처리 해보면 n^n의 Time complexity가 나타나게 된다.
이것을 해결하는 방법은 Memorization을 사용하는 것이다.
상기 예를 조금 줄여 보도록 하겠다.
s = "aaaaaaa", wordDict = ["a","aa", "aaa"]
있다고 하면 나올 수 있는 경우의 수는 다음과 같다.
- a + aaaaaaa
- a + aaaaaa
- a + aaaaa
- .....
-
- a => true
- aa + aaaa
- aaa + aaa
- a + aaaaa
- aa + aaaaa
- aaa + aaaa
- a + aaaaaa
- aa + aaaaaa
- aaa + aaaaa
상기와 같이 a가 true라는 사실을 알게 되고
a + aaaaa
가 true라는 사실을 저장해 놓는다면
- aa + aaaaaa
와 같이 a가 6개인 경우는 true 임으로 더 이상 처리 할 필요 없이, true 처리 되면 된다.
이와 같은 Memorization을 바탕으로 O(N^2)까지 Time complexity가 내려가게 된다.
Memorization의 시간 복잡도는 아직도 어떻게 계산해야 할지 모르겠다. 그래서 다른 사람이 정리해 놓은 링크를 걸어 놓는다.
The Time Complexity of The Brute Force Method Should Be O(2^n) and Prove It Below - LeetCode Discuss
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
상기와 같은 취지를 바탕으로 2가지 방식으로 Trie형 프로그램을 만들어 보았다.
- BFS
- DFS
Trie형은 불필요 했던거 같은데 혹시 궁금하면 참고 바란다.
//노드 정의
class Node {
constructor(val) {
this.val = val;
this.next = new Map();
this.end = false;
}
}
var wordBreak = function(s, wordDict) {
//Trie 루트 노드
let root = new Node('');
let dp = new Map(); // Trie 조회 결과 DP
let dpDfs = new Map(); // word 조회 결과 DP
//Trie 생성
wordDict.forEach(word => buildWordsMap(word));
//BFS를 통한 모든 경우 조회
// BFS -> n^n
// let queue = new Array();
// queue.push(s);
// while (queue.length) {
// let curString = queue.shift();
// if(curString == '') return true;
// let nextPositions = searchWord(curString);
//
// nextPositions.forEach(position => {
// queue.push(curString.slice(position+1));
// });
// }
//DFS를 통한 word Memorization
return dfs(s);
// DFS 조회
function dfs(word){
if(dpDfs.has(word)){
return dpDfs.get(word);
}
if(word == '') return true;
let arrs = searchWord(word);
for (let i = 0; i < arrs.length; i++) {
let position = arrs[i];
if(dfs(word.slice(position+1))){
dpDfs.set(word,true);
return true;
}
}
dpDfs.set(word,false);
return false;
}
// Trie 조회
function searchWord(word){
if(dp.has(word)){
return dp.get(word);
}
let origin = word;
let node = root;
let result = [];
let count = 0;
while (node.next.has(word.charAt(0))) {
node = node.next.get(word.charAt(0));
word = word.slice(1);
if (node.end) {
result.push(count);
}
count++;
}
dp.set(origin, result);
return result;
}
// Trie 생성
function buildWordsMap(word){
let node = root;
while(0 < word.length){
if(!node.next.has(word.charAt(0))){
node.next.set(word.charAt(0), new Node(word.charAt(0)));
}
node = node.next.get(word.charAt(0));
word = word.slice(1);
}
node.end = true;
}
};
처음에 BFS를 이용해서 word를 찾는 방법을 만들어 보았는데,
이경우는 Memorization이 불가능 해서 DFS로 다시 만들어서 Memorization처리 했다.
최근에 새삼스럽게 이 문제를 다시 풀어 봤다.
방법은 동일 하긴 한데 코드는 조금 달라서 여기에 추가한다. (물론 풀때는 이 문제 풀었던거 기억이 안나서 난감 ㅠㅠ)
/**
* @param {string} s
* @param {string[]} wordDict
* @return {boolean}
*/
var wordBreak = function(s, wordDict) {
let dictMap = new Map();
let wordsMap = new Map();
let dp = new Array(s.length).fill(null);
for(const word of wordDict){
buildNode(word);
}
// console.log(dp);
return helper(s,0);
function helper(str,position){
if(dp[position] !== null) return dp[position];
if(wordsMap.has(str)) return dp[position] = true;
const arr = journeyNode(str);
for(let idx of arr){
if(helper(str.substring(idx+1),position + idx + 1)) return dp[position] = true;
}
return dp[position] = false;
}
function journeyNode(str){
let wordMap = dictMap;
let result = new Array();
let breakWord = '';
for(let i = 0; i < str.length; i++){
const char = str.charAt(i);
breakWord += char;
if(wordMap.has(char)){
wordMap = wordMap.get(char);
if(wordsMap.has(breakWord)){
result.push(i);
}
} else {
break;
}
}
return result;
}
function buildNode(word){
wordsMap.set(word,true);
let wordMap = dictMap;
for(let i = 0; i < word.length; i++){
const char = word.charAt(i);
if(!wordMap.has(char)){
wordMap.set(char, new Map());
}
wordMap = wordMap.get(char);
}
}
};
'Problem Solving' 카테고리의 다른 글
Maximum Distance in Arrays (0) | 2020.10.03 |
---|---|
39. Combination Sum (0) | 2020.10.03 |
Subarray Product Less Than K (0) | 2020.09.29 |
프로그래머스 vs code jest 사용법 (0) | 2020.09.26 |
Largest Number (0) | 2020.09.26 |