-
-
Notifications
You must be signed in to change notification settings - Fork 195
[uraflower] Week 15 Solutions #1663
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
Changes from all commits
86cd574
9452a52
1022935
a16a983
89a79b3
b12780a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/** | ||
* @param words: a list of words | ||
* @return: a string which is correct order | ||
*/ | ||
const alienOrder = (words) => { | ||
const graph = {}; | ||
|
||
// 초기화 | ||
for (const word of words) { | ||
for (const char of word) { | ||
if (!graph[char]) { | ||
graph[char] = new Set(); | ||
} | ||
} | ||
} | ||
|
||
// 그래프 생성 | ||
for (let i = 1; i < words.length; i++) { | ||
const prev = words[i - 1]; | ||
const current = words[i]; | ||
let found = false; | ||
|
||
const minLen = Math.min(prev.length, current.length); | ||
for (let j = 0; j < minLen; j++) { | ||
if (prev[j] !== current[j]) { | ||
graph[prev[j]].add(current[j]); | ||
found = true; | ||
break; | ||
} | ||
} | ||
// 모순 처리 | ||
if (!found && prev.length > current.length) { | ||
return ''; | ||
} | ||
} | ||
|
||
// 탐색 | ||
const output = []; | ||
const visiting = new Set(); | ||
const visited = new Set(); | ||
|
||
function dfs(current) { | ||
if (visiting.has(current)) { | ||
return false; | ||
} | ||
if (visited.has(current)) { | ||
return true; | ||
} | ||
|
||
visiting.add(current); | ||
for (const adj of graph[current]) { | ||
if (!dfs(adj)) { | ||
return false; | ||
} | ||
} | ||
visiting.delete(current); | ||
|
||
visited.add(current); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 이 문제를 위상정렬(BFS)로 풀었는데요, DFS로 풀려면 indegree를 기록할 필요 없이 이렇게 상태를 하나 더 유지해서 풀 수 있군요! |
||
output.push(current); | ||
return true; | ||
} | ||
|
||
// 순회 | ||
for (const node in graph) { | ||
if (!dfs(node)) { | ||
return ''; | ||
} | ||
} | ||
|
||
return output.reverse().join(''); | ||
} | ||
|
||
|
||
// 방향 그래프로 선행되는 순서를 표현 | ||
// 비슷한 문제: https://leetcode.com/problems/course-schedule/description/ | ||
|
||
// 위상정렬 사용해서 진입차수 기준 정렬하는 방법도 있음 | ||
// 너무 어려웠다... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// 접근법 | ||
// preorder: v l r | ||
// inorder: l v r | ||
|
||
// preorder의 가장 첫 요소는 무조건 root | ||
// inorder에서 root보다 왼쪽에 있는 요소는 전부 left임 | ||
// 여기서 중복되는 value가 없어야 하는데 문제에서 없음을 보장함 | ||
// 따라서 preorder[0]을 inorder에서 찾고 | ||
// 그 왼쪽, 오른쪽으로 배열을 나눠서 이걸 반복 | ||
|
||
/** | ||
* Definition for a binary tree node. | ||
* function TreeNode(val, left, right) { | ||
* this.val = (val===undefined ? 0 : val) | ||
* this.left = (left===undefined ? null : left) | ||
* this.right = (right===undefined ? null : right) | ||
* } | ||
*/ | ||
/** | ||
* @param {number[]} preorder | ||
* @param {number[]} inorder | ||
* @return {TreeNode} | ||
*/ | ||
const buildTree = function (preorder, inorder) { | ||
let preorderIndex = 0; | ||
const map = inorder.reduce((map, val, index) => { | ||
map[val] = index; | ||
return map; | ||
}, {}); | ||
|
||
function build(start, end) { | ||
if (start > end) { | ||
return null; | ||
} | ||
|
||
const root = new TreeNode(preorder[preorderIndex++]); | ||
const index = map[root.val]; | ||
|
||
root.left = build(start, index - 1); | ||
root.right = build(index + 1, end); | ||
|
||
return root; | ||
} | ||
|
||
return build(0, inorder.length - 1); | ||
}; | ||
|
||
// 시간복잡도: O(n) | ||
// 공간복잡도: O(n) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* @param {string} s | ||
* @return {string} | ||
*/ | ||
const longestPalindrome = function(s) { | ||
let substr = ''; | ||
|
||
for (let i = 0; i < s.length; i++) { | ||
const oddStr = getCurrentLongestPalindrome(i, i); // s[i] 기준 양옆으로 뻗어나감 => length는 항상 홀수 | ||
const evenStr = getCurrentLongestPalindrome(i, i+1); // s[i] + s[i+1] 기준 양옆으로 => length는 항상 짝수 | ||
|
||
if (substr.length < oddStr.length) substr = oddStr; | ||
if (substr.length < evenStr.length) substr = evenStr; | ||
} | ||
|
||
// 기준 문자열을 포함하면서 가장 긴 팰린드롬을 찾아 반환하는 함수 (기준 문자열: s.slice(l, r + 1)) | ||
const getCurrentLongestPalindrome = function (l, r) { | ||
while (0 <= l && r < s.length && s[l] === s[r]) { | ||
l--; | ||
r++; | ||
} | ||
|
||
return s.slice(l+1, r); | ||
} | ||
|
||
return substr; | ||
}; | ||
|
||
// 시간복잡도: O(n^2) | ||
// 공간복잡도: O(s) (s: substr.length) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* @param {number[][]} matrix | ||
* @return {void} Do not return anything, modify matrix in-place instead. | ||
*/ | ||
const rotate = function (matrix) { | ||
const n = matrix.length; | ||
|
||
// 상하좌우 겉에서부터 한 겹씩 안으로 진입 | ||
for (let layer = 0; layer < Math.floor(n / 2); layer++) { | ||
|
||
// layer 위의 각 칸들을 rotate | ||
// 하나를 rotate했을 때 연쇄적으로 rotate되는 규칙을 이용해 | ||
// 네 칸 rotate하는 걸 x번 반복함 | ||
|
||
// x = n - 2 * layer - 1 | ||
// 전체 배열 크기 n에서 layer만큼 안쪽으로 들어가야 하는데 | ||
// 상하, 좌우만큼 들어가야 하니까 2를 곱함 | ||
// 1을 안 빼면 이미 rotate한 자리를 다시 rotate하므로 빼줌 | ||
|
||
for (let i = 0; i < n - 2 * layer - 1; i++) { | ||
const top = layer; | ||
const bottom = n - 1 - layer; | ||
const left = top; | ||
const right = bottom; | ||
|
||
const topLeft = matrix[top][left + i]; | ||
matrix[top][left + i] = matrix[bottom - i][left]; | ||
matrix[bottom - i][left] = matrix[bottom][right - i]; | ||
matrix[bottom][right - i] = matrix[top + i][right]; | ||
matrix[top + i][right] = topLeft; | ||
} | ||
} | ||
}; | ||
|
||
// 시간복잡도: O(n^2) | ||
// 공간복잡도: O(1) | ||
|
||
// 참고로 중첩 구조를 다음과 같이 바꿔도 됨 | ||
const top = 0; | ||
const bottom = n - 1; | ||
|
||
while (top < bototm) { | ||
const left = top; | ||
const right = bottom; | ||
|
||
for (let i = top; i < bottom; i ++) { | ||
// rotate | ||
} | ||
|
||
top++; | ||
bottom--; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* Definition for a binary tree node. | ||
* function TreeNode(val, left, right) { | ||
* this.val = (val===undefined ? 0 : val) | ||
* this.left = (left===undefined ? null : left) | ||
* this.right = (right===undefined ? null : right) | ||
* } | ||
*/ | ||
/** | ||
* @param {TreeNode} root | ||
* @param {TreeNode} subRoot | ||
* @return {boolean} | ||
*/ | ||
const isSubtree = function(root, subRoot) { | ||
const isSame = function(node1, node2) { | ||
if (!node1 && !node2) return true; | ||
if (node1?.val !== node2?.val) return false; | ||
|
||
return isSame(node1.left, node2.left) && isSame(node1.right, node2.right); | ||
} | ||
|
||
const queue = [root]; | ||
|
||
while (queue.length) { | ||
const node = queue.shift(); | ||
|
||
if (node.left) { | ||
queue.push(node.left); | ||
} | ||
|
||
if (node.right) { | ||
queue.push(node.right); | ||
} | ||
|
||
if (isSame(node, subRoot)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BFS로 |
||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
// 다른 접근법: | ||
// 정렬해서 비교하는 방식 => left, right 구분이 안가는 문제 | ||
// 정렬할 때 left, right 정보를 포함해서 직렬화하면 됨 | ||
// 이렇게 하면 복잡도 면에서 성능이 더 좋음 | ||
|
||
// 시간복잡도: O(n * m) (n: root size, m: subroot size) | ||
// 공간복잡도: O(n + m) |
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.
minLen
내 인덱스 범위에서prev
와current
간 문자쌍 중 처음으로 서로 다른 문자까지만graph
에 추가해야 할 것 같은데요(그 이후 문자는 더이상 비교할 수 없기 때문), 현재 코드에서는minLen
까지 모든 범위에 대해graph
를 구성하고 있는 것 같아요!그리고 현재 코드에서는
found
변수를true
로 바꾸는 코드가 없어서 항상false
인 것 같습니다!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.
헉 제가 무료 버전에서 풀다가 실행시키려고 다른 편집기에서 작성했는데 그래서 풀다 만 버전으로 잘못 올렸네요.
꼼꼼히 봐주시고 말씀해주셔서 정말 감사합니다! 😄