-
Notifications
You must be signed in to change notification settings - Fork 126
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
[강희찬] WEEK 9 Solution #519
Changes from all commits
a0cc746
33bca46
9a46c55
aff0d63
cd17daa
5d0a623
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,20 @@ | ||
/** | ||
* https://leetcode.com/problems/find-minimum-in-rotated-sorted-array | ||
* T.C. O(log n) | ||
* S.C. O(1) | ||
*/ | ||
function findMin(nums: number[]): number { | ||
let left = 0; | ||
let right = nums.length - 1; | ||
let mid = (left + right) >> 1; | ||
|
||
while (left < right) { | ||
if (nums[mid] > nums[right]) { | ||
left = mid + 1; | ||
} else { | ||
right = mid; | ||
} | ||
mid = (left + right) >> 1; | ||
} | ||
return nums[left]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
class ListNode { | ||
val: number; | ||
next: ListNode | null; | ||
constructor(val?: number, next?: ListNode | null) { | ||
this.val = val === undefined ? 0 : val; | ||
this.next = next === undefined ? null : next; | ||
} | ||
} | ||
|
||
/** | ||
* https://leetcode.com/problems/linked-list-cycle | ||
* T.C. O(n) | ||
* S.C. O(n) | ||
*/ | ||
function hasCycle(head: ListNode | null): boolean { | ||
const SET = new Set<ListNode>(); | ||
while (head) { | ||
if (SET.has(head)) return true; | ||
SET.add(head); | ||
head = head.next | ||
} | ||
return false; | ||
Comment on lines
+15
to
+22
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. fast와 slow만 사용하는걸 생각헀는데, 창의적인 답인것 같아요! |
||
}; | ||
|
||
/** | ||
* T.C. O(n) | ||
* S.C. O(1) | ||
*/ | ||
function hasCycle(head: ListNode | null): boolean { | ||
let fast = head; | ||
let slow = head; | ||
|
||
while (fast && fast.next) { | ||
fast = fast.next.next; | ||
slow = slow!.next; | ||
|
||
if (fast === slow) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/** | ||
* https://leetcode.com/problems/maximum-subarray | ||
* Kadane's Algorithm | ||
* T.C. O(n) | ||
* S.C. O(1) | ||
*/ | ||
function maxSubArray(nums: number[]): number { | ||
let maxSum = nums[0]; | ||
|
||
for (let i = 1; i < nums.length; i++) { | ||
nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]); | ||
maxSum = Math.max(maxSum, nums[i]); | ||
} | ||
|
||
return maxSum; | ||
Comment on lines
+7
to
+15
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. 성능만 따지자면 세개의 답중 가장 느리고 공간 효율도 안좋지만, 가독성 측면에서 봤을때는 너무 좋은것 같아요. 개인적으로 이 코드가 제일 마음에 들어요 :) |
||
} | ||
|
||
/** | ||
* Divide and Conquer version | ||
* T.C. O(n log n) | ||
* S.C. O(log n) - call stack | ||
*/ | ||
function maxSubArray(nums: number[]): number { | ||
function maxSubArrayHelper( | ||
nums: number[], | ||
left: number, | ||
right: number | ||
): number { | ||
if (left === right) return nums[left]; | ||
|
||
const mid = (left + right) >> 1; | ||
const leftMax = maxSubArrayHelper(nums, left, mid); | ||
const rightMax = maxSubArrayHelper(nums, mid + 1, right); | ||
let leftSum = -Infinity; | ||
let rightSum = -Infinity; | ||
let sum = 0; | ||
|
||
for (let i = mid; i >= left; i--) { | ||
sum += nums[i]; | ||
leftSum = Math.max(leftSum, sum); | ||
} | ||
|
||
sum = 0; | ||
for (let i = mid + 1; i <= right; i++) { | ||
sum += nums[i]; | ||
rightSum = Math.max(rightSum, sum); | ||
} | ||
|
||
return Math.max(leftMax, rightMax, leftSum + rightSum); | ||
} | ||
|
||
return maxSubArrayHelper(nums, 0, nums.length - 1); | ||
} | ||
|
||
/** | ||
* Iterative version | ||
* T.C. O(n log n) | ||
* S.C. O(log n) - call stack | ||
*/ | ||
function maxSubArray(nums: number[]): number { | ||
const stack = [[0, nums.length - 1]]; | ||
let maxSum = nums[0]; | ||
|
||
while (stack.length) { | ||
const [left, right] = stack.pop()!; | ||
if (left === right) { | ||
maxSum = Math.max(maxSum, nums[left]); | ||
continue; | ||
} | ||
|
||
const mid = (left + right) >> 1; | ||
stack.push([left, mid], [mid + 1, right]); | ||
|
||
let leftSum = -Infinity; | ||
let rightSum = -Infinity; | ||
let sum = 0; | ||
|
||
for (let i = mid; i >= left; i--) { | ||
sum += nums[i]; | ||
leftSum = Math.max(leftSum, sum); | ||
} | ||
|
||
sum = 0; | ||
for (let i = mid + 1; i <= right; i++) { | ||
sum += nums[i]; | ||
rightSum = Math.max(rightSum, sum); | ||
} | ||
|
||
maxSum = Math.max(maxSum, leftSum + rightSum); | ||
} | ||
|
||
return maxSum; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* https://leetcode.com/problems/minimum-window-substring | ||
* T.C. O(s + t) | ||
* S.C. O(t) | ||
*/ | ||
function minWindow(s: string, t: string): string { | ||
let minLow = 0; | ||
let minHigh = s.length; | ||
|
||
const counts: Record<string, number> = {}; | ||
for (const c of t) { | ||
counts[c] = (counts[c] || 0) + 1; | ||
} | ||
|
||
let included = 0; | ||
|
||
let low = 0; | ||
for (let high = 0; high < s.length; high++) { | ||
if (counts[s[high]]) { | ||
if (counts[s[high]] > 0) { | ||
included++; | ||
} | ||
counts[s[high]]--; | ||
} | ||
|
||
while (included === t.length) { | ||
if (high - low < minHigh - minLow) { | ||
minLow = low; | ||
minHigh = high; | ||
} | ||
|
||
if (counts[s[low]]) { | ||
counts[s[low]]++; | ||
if (counts[s[low]] > 0) { | ||
included--; | ||
} | ||
} | ||
|
||
low++; | ||
} | ||
} | ||
|
||
return minHigh === s.length ? '' : s.substring(minLow, minHigh + 1); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/** | ||
* https://leetcode.com/problems/pacific-atlantic-water-flow | ||
* T.C. O((m * n)^2) | ||
* S.C. O(m * n) | ||
*/ | ||
function pacificAtlantic(heights: number[][]): number[][] { | ||
const dir = [ | ||
[0, 1], | ||
[0, -1], | ||
[1, 0], | ||
[-1, 0], | ||
]; | ||
|
||
function pacificDfs(row: number, col: number, visited: Set<string>) { | ||
const key = `${row},${col}`; | ||
if (visited.has(key)) return; | ||
visited.add(key); | ||
|
||
if (row === 0 || col === 0) { | ||
// left or top | ||
return true; | ||
} | ||
|
||
for (let [r, c] of dir) { | ||
if (row + r < 0 || row + r >= heights.length) continue; | ||
if (col + c < 0 || col + c >= heights[0].length) continue; | ||
if (heights[row][col] < heights[row + r][col + c]) continue; | ||
if (pacificDfs(row + r, col + c, visited)) return true; | ||
} | ||
return false; | ||
} | ||
|
||
function atlanticDfs(row: number, col: number, visited: Set<string>) { | ||
const key = `${row},${col}`; | ||
if (visited.has(key)) return; | ||
visited.add(key); | ||
|
||
if (row === heights.length - 1 || col === heights[0].length - 1) { | ||
// right or bottom | ||
return true; | ||
} | ||
|
||
for (let [r, c] of dir) { | ||
if (row + r < 0 || row + r >= heights.length) continue; | ||
if (col + c < 0 || col + c >= heights[0].length) continue; | ||
if (heights[row][col] < heights[row + r][col + c]) continue; | ||
if (atlanticDfs(row + r, col + c, visited)) return true; | ||
} | ||
return false; | ||
} | ||
|
||
const result: number[][] = []; | ||
for (let i = 0; i < heights.length; i++) { | ||
for (let j = 0; j < heights[0].length; j++) { | ||
if ( | ||
pacificDfs(i, j, new Set<string>()) && | ||
atlanticDfs(i, j, new Set<string>()) | ||
) { | ||
result.push([i, j]); | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
/** | ||
* T.C. O(m * n) | ||
* S.C. O(m * n) | ||
Comment on lines
+68
to
+69
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. 시간 복잡도를 ^2이나 줄이시는 과정이 눈에 보여서 좋은것 같아요 :) |
||
*/ | ||
function pacificAtlantic(heights: number[][]): number[][] { | ||
const pacific: Set<string> = new Set(); | ||
const atlantic: Set<string> = new Set(); | ||
|
||
const dir = [ | ||
[0, 1], | ||
[0, -1], | ||
[1, 0], | ||
[-1, 0], | ||
]; | ||
|
||
function dfs(row: number, col: number, visited: Set<string>) { | ||
const key = `${row},${col}`; | ||
if (visited.has(key)) return; | ||
visited.add(key); | ||
|
||
for (let [r, c] of dir) { | ||
if (row + r < 0 || row + r >= heights.length) continue; | ||
if (col + c < 0 || col + c >= heights[0].length) continue; | ||
if (heights[row][col] > heights[row + r][col + c]) continue; | ||
dfs(row + r, col + c, visited); | ||
} | ||
} | ||
|
||
for (let i = 0; i < heights.length; i++) { | ||
dfs(i, 0, pacific); | ||
dfs(i, heights[0].length - 1, atlantic); | ||
} | ||
|
||
for (let i = 0; i < heights[0].length; i++) { | ||
dfs(0, i, pacific); | ||
dfs(heights.length - 1, i, atlantic); | ||
} | ||
|
||
const result: number[][] = []; | ||
|
||
for (const p of pacific) { | ||
if (atlantic.has(p)) { | ||
const [row, col] = p.split(',').map(Number); | ||
result.push([row, col]); | ||
} | ||
} | ||
|
||
return result; | ||
} |
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.
mid 값 구하는데
(left + right) / 2
만 생각했는데, 이렇게 하면 비트 연산으로 더 효율적이겠네요..! 하나 배웠습니다 :)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.
// 2 보다 우아하네요. mid에 대해 첨언드리자면 정수형 변수의 크기가 가변적이지 않은 언어의 경우 left + (right - left) // 2 같은 방식으로 mid를 계산해서 overflow를 방지하는 방식도 있습니다.