-
-
Notifications
You must be signed in to change notification settings - Fork 195
[JANGSEYEONG] WEEK 05 solutions #1390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* 시간 복잡도: O(n) - 배열을 한 번만 순회함 | ||
* 공간 복잡도: O(1) - 추가 배열 없이 변수만 사용하므로 입력 크기와 무관한 상수 공간 | ||
*/ | ||
/** | ||
* @param {number[]} prices | ||
* @return {number} | ||
*/ | ||
var maxProfit = function (prices) { | ||
let minPrice = prices[0]; // 지금까지 본 가장 낮은 가격 | ||
let maxProfit = 0; // 최대 이익 | ||
for (let i = 1; i < prices.length; i++) { | ||
if (prices[i] > minPrice) { | ||
// 현재 가격이 minPrice보다 큰 경우에 이익 갱신 | ||
maxProfit = Math.max(maxProfit, prices[i] - minPrice); | ||
} else { | ||
// 그렇지 않다면 최소 가격 갱신 | ||
minPrice = prices[i]; | ||
} | ||
} | ||
return maxProfit; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/** | ||
* 시간 복잡도: O(n) - n은 모든 문자열의 총 길이. 각 문자를 한 번씩만 처리함 | ||
* 공간 복잡도: O(n) - 인코딩/디코딩 결과를 저장하는 데 원본 데이터 크기만큼 공간 필요 | ||
*/ | ||
var encode = function (strs) { | ||
let text = ""; | ||
for (let str of strs) { | ||
// 각 문자열 앞에 길이와 구분자(:)를 붙여서 저장 | ||
// 예: ["abc", "de"] -> "3:abc2:de" | ||
text += `${str.length}:${str}`; | ||
} | ||
return text; | ||
}; | ||
|
||
var decode = function (s) { | ||
const result = []; | ||
let start = 0; | ||
|
||
while (start < s.length) { | ||
// 가장 첫번째에 등장하는 콜론 위치를 찾아 길이 정보 추출 | ||
const mid = s.indexOf(":", start); | ||
const length = parseInt(s.substring(start, mid)); | ||
|
||
// 길이 정보를 이용해 원래 문자열 추출하여 결과 배열에 추가 | ||
result.push(s.substring(mid + 1, mid + 1 + length)); | ||
|
||
// 다음 문자열의 시작 위치로 이동 | ||
start = mid + 1 + length; | ||
} | ||
|
||
return result; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* 첫번쨰 풀이: 각 단어마다 이전에 처리한 단어들과 일일이 비교하여 애너그램 여부 확인 | ||
* 첫번째 풀이로도 통과는 함 | ||
* 시간복잡도: O(n²*k), 공간복잡도: O(n*k) (n: 단어 수, k: 평균 단어 길이) | ||
*/ | ||
/*var groupAnagrams = function (strs) { | ||
if (strs.length === 1) return [strs]; | ||
|
||
const answer = [[strs[0]]]; | ||
|
||
for (let i = 1; i < strs.length; i++) { | ||
let flag = false; | ||
for (let k = 0; k < answer.length; k++) { | ||
const word = answer[k][0]; | ||
if (isAnagram(word, strs[i])) { | ||
answer[k].push(strs[i]); | ||
flag = true; | ||
} | ||
} | ||
if (!flag) answer.push([strs[i]]); | ||
} | ||
|
||
return answer; | ||
}; | ||
|
||
var isAnagram = function (s1, s2) { | ||
if (s1.length !== s2.length) return false; | ||
|
||
// 영어 소문자 개수 총 26개 | ||
const code = new Array(26).fill(0); | ||
|
||
for (let i = 0; i < s1.length; i++) { | ||
code[s1[i].charCodeAt() - 97]++; | ||
code[s2[i].charCodeAt() - 97]--; | ||
} | ||
return code.every((x) => x === 0); | ||
}; | ||
*/ | ||
/////////////////////////////////////////////////////////////// | ||
|
||
/* | ||
* 두번쨰 풀이: 정렬된 문자열을 키로 사용하여 해시맵에 그룹화 | ||
* 시간복잡도: O(n*k*log(k)), 공간복잡도: O(n*k) (n: 단어 수, k: 평균 단어 길이) | ||
*/ | ||
/** | ||
* @param {string[]} strs | ||
* @return {string[][]} | ||
*/ | ||
var groupAnagrams = function (strs) { | ||
if (strs.length === 1) return [strs]; | ||
|
||
// 해시맵으로 애너그램 그룹 관리 | ||
const answer = {}; | ||
|
||
for (let i = 0; i < strs.length; i++) { | ||
// 애너그램은 정렬하면 동일한 문자열이 됨 | ||
// k는 최대 100으로 제한되어 있어 정렬(O(k log k))이 효율적이므로 | ||
// 첫 번째 풀이의 카운팅 방식 대신 간단히 정렬로 판별 가능 | ||
const sort = [...strs[i]].sort().join(""); | ||
|
||
// 이미 같은 키가 있으면 해당 그룹에 추가 | ||
if (sort in answer) { | ||
answer[sort].push(strs[i]); | ||
} else { | ||
// 새로운 그룹 생성 | ||
answer[sort] = [strs[i]]; | ||
} | ||
} | ||
|
||
return Object.values(answer); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/** | ||
* Trie(트라이) 데이터 구조 구현 | ||
* | ||
* 원리: 트라이는 문자열을 효율적으로 저장하고 검색하기 위한 트리 구조 | ||
* 각 노드는 한 문자를 나타내며, 루트에서 특정 노드까지의 경로가 하나의 문자열이 된다 | ||
* 공통 접두사를 공유하여 메모리를 절약하고, 접두사 검색을 O(k) 시간에 수행할 수 있음 | ||
*/ | ||
var Trie = function () { | ||
this.root = {}; // 루트 노드 | ||
}; | ||
|
||
/** | ||
* @param {string} word | ||
* @return {void} | ||
*/ | ||
Trie.prototype.insert = function (word) { | ||
let node = this.root; | ||
|
||
for (let char of word) { | ||
if (!node[char]) { | ||
// 처음 들어오는 단어일 경우, 새 트리구조 생성 | ||
node[char] = {}; | ||
} | ||
// 현재 단어 위치로 이동 | ||
node = node[char]; | ||
} | ||
node.isEnd = true; // 단어 끝 표시 | ||
}; | ||
|
||
/** | ||
* @param {string} word | ||
* @return {boolean} | ||
*/ | ||
Trie.prototype.search = function (word) { | ||
let node = this.traverse(word); | ||
return node !== null && node.isEnd === true; | ||
}; | ||
|
||
/** | ||
* @param {string} prefix | ||
* @return {boolean} | ||
*/ | ||
Trie.prototype.startsWith = function (prefix) { | ||
return this.traverse(prefix) !== null; | ||
}; | ||
|
||
/** | ||
* 주어진 문자열을 따라 트라이를 탐색하는 함수 | ||
* @param {string} str - 트라이에서 탐색할 문자열 | ||
* @return {object|null} - 문자열 경로의 마지막 노드 또는 경로가 없으면 null | ||
*/ | ||
Trie.prototype.traverse = function (str) { | ||
let node = this.root; | ||
|
||
// 문자열의 각 문자를 하나씩 순회 | ||
for (let char of str) { | ||
// 현재 문자에 대한 경로가 없으면 탐색 실패 | ||
if (!node[char]) { | ||
return null; | ||
} | ||
// 해당 문자의 노드로 이동하여 탐색 계속 | ||
node = node[char]; | ||
} | ||
return node; | ||
}; | ||
|
||
/** | ||
* Your Trie object will be instantiated and called as such: | ||
* var obj = new Trie() | ||
* obj.insert(word) | ||
* var param_2 = obj.search(word) | ||
* var param_3 = obj.startsWith(prefix) | ||
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* 문자열이 단어 사전 내의 단어들로 분할 가능한지 확인 | ||
* | ||
* 시간복잡도: O(n * m * k) | ||
* - n: 문자열 길이 | ||
* - m: 단어 사전 크기 | ||
* - k: 단어 사전 내 가장 긴 단어의 길이 | ||
* | ||
* 공간복잡도: O(n) | ||
* - n: 문자열 길이 (메모이제이션 저장 공간) | ||
* | ||
* @param {string} s - 분할하려는 문자열 | ||
* @param {string[]} wordDict - 단어 사전 | ||
* @return {boolean} - 문자열을 단어 사전 내 단어들로 분할 가능한지 여부 | ||
*/ | ||
var wordBreak = function (s, wordDict) { | ||
// 메모이제이션을 위한 객체 | ||
const memo = {}; | ||
|
||
const dfs = function (start) { | ||
// 이미 계산한 위치라면 저장된 결과 반환 | ||
if (start in memo) return memo[start]; | ||
|
||
// 문자열 끝까지 도달했다면 성공 | ||
if (start === s.length) { | ||
memo[start] = true; | ||
return true; | ||
} | ||
|
||
// 모든 단어를 시도 | ||
for (const word of wordDict) { | ||
// 현재 위치에서 시작하는 부분 문자열이 단어와 일치하는지 확인 | ||
if (s.substring(start, start + word.length) === word) { | ||
// 남은 문자열도 분할 가능한지 재귀적으로 확인 | ||
if (dfs(start + word.length)) { | ||
memo[start] = true; | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
// 현재 위치에서 가능한 분할이 없음 | ||
memo[start] = false; | ||
return false; | ||
}; | ||
|
||
return dfs(0); | ||
}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요 세영님. 갑자기 보여서 구경하고갑니다🤓
첫번째 풀이
isAnagram
을 조금만 변형해서 생각하면 두번째 풀이에서 정렬하지않고도 구분할 수 있는 key값을 얻을 수 있습니다String.prototype.substring은 안써봤는데 배워갑니다~