Skip to content

Commit

Permalink
Merge pull request #548 from obzva/main
Browse files Browse the repository at this point in the history
[Flynn] week 11
  • Loading branch information
obzva authored Oct 26, 2024
2 parents e6c6b28 + 5000053 commit c3ee69e
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
61 changes: 61 additions & 0 deletions binary-tree-maximum-path-sum/flynn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
ํ’€์ด
- post order traversal dfs๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ’€์ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
Big O
- N: node์˜ ๊ฐœ์ˆ˜
- H: Tree์˜ ๋†’์ด
- Time compleixty: O(N)
- ๋ชจ๋“  node๋ฅผ ์ตœ๋Œ€ ํ•œ ๋ฒˆ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค
- Space complexity: O(H)
- ์žฌ๊ท€ ํ˜ธ์ถœ ์Šคํƒ์˜ ๊นŠ์ด๋Š” H์— ๋น„๋ก€ํ•˜์—ฌ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค
*/

/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxPathSum(root *TreeNode) int {
res := root.Val

var maxSubtreeSum func(*TreeNode) int
maxSubtreeSum = func(node *TreeNode) int {
// base case
if node == nil {
return 0
}
// left subtree๋กœ ๋‚ด๋ ค๊ฐ”์„ ๋•Œ ๊ตฌํ•  ์ˆ˜ ์žˆ๋Š” maximum path sum
// left subtree๋กœ path๋ฅผ ๋‚ด๋ ค๊ฐ”์„ ๋•Œ, left subtree๊ฐ€ sum์— ๊ธฐ์—ฌํ•˜๋Š” ๊ฐ’์ด 0๋ณด๋‹ค ์ž‘์„ ๊ฒฝ์šฐ
// left subtree๋กœ๋Š” path๋ฅผ ๋‚ด๋ ค๊ฐ€์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Œ
// ๋”ฐ๋ผ์„œ left < 0 ์ธ ๊ฒฝ์šฐ์—” left = 0
left := maxSubtreeSum(node.Left)
if left < 0 {
left = 0
}
// right subtree๋„ left subtree์™€ ๋™์ผํ•จ
right := maxSubtreeSum(node.Right)
if right < 0 {
right = 0
}
// ํ˜„์žฌ ํƒ์ƒ‰ํ•˜๊ณ  ์žˆ๋Š” node์˜ ์กฐ์ƒ node๋ฅผ path์— ํฌํ•จํ•˜์ง€ ์•Š๊ณ ๋„
// maxPathSum์ด ๊ตฌํ•ด์ง€๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ
if res < left+right+node.Val {
res = left + right + node.Val
}
// ํ˜„์žฌ๊นŒ์ง€ ๊ณ„์‚ฐํ•œ subtree path sum์„ ๋ถ€๋ชจ node์—๊ฒŒ ์ „๋‹ฌํ•ด์•ผ ํ•จ
// ํ˜„์žฌ node์˜ ๋ถ€๋ชจ์™€ ์ด์–ด์ง€๋Š” path์—ฌ์•ผ ํ•˜๋ฏ€๋กœ, node.Val + max(left, right)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋จ
subTreeSum := node.Val
if left > right {
subTreeSum += left
} else {
subTreeSum += right
}
return subTreeSum
}

maxSubtreeSum(root)
return res
}
57 changes: 57 additions & 0 deletions graph-valid-tree/flynn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
ํ’€์ด
- valid tree์ธ์ง€ ํŒ๋ณ„ํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค
์ฃผ์–ด์ง„ input์ด valid tree์ด๋ ค๋ฉด,
1. cycle์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (cycle์ด ์žˆ๋Š” ๊ฒฝ์šฐ: [[0, 1], [1, 2], [2, 0]])
2. ๋ชจ๋“  node๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (๋ชจ๋“  node๊ฐ€ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: [[0, 1], [2, 3]])
- dfs ๋ฐฉ์‹์˜ ํ•จ์ˆ˜๋ฅผ ์žฌ๊ท€ ํ˜ธ์ถœํ•˜์—ฌ ํ’€์ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
Big O
- N: n
- E: ์ฃผ์–ด์ง„ ๋ฐฐ์—ด edges์˜ ํฌ๊ธฐ
- Time complexity: O(N)
- ๋ชจ๋“  node๋ฅผ ์ตœ๋Œ€ 1๋ฒˆ์”ฉ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค
- Space complexity: O(E + N)
- visited์˜ ํฌ๊ธฐ๋Š” N์— ๋น„๋ก€ํ•˜์—ฌ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค -> O(N)
- adj์˜ ํฌ๊ธฐ๋Š” E์— ๋น„๋ก€ํ•˜์—ฌ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค -> O(E)
- dfs์˜ ์žฌ๊ท€ํ˜ธ์ถœ ์Šคํƒ ๊นŠ์ด๋Š” ์ตœ์•…์˜ ๊ฒฝ์šฐ N๊นŒ์ง€ ์ปค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค -> O(N)
*/

func validTree(n int, edges [][]int) bool {
// valid tree๋Š” n-1๊ฐœ์˜ edge๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ๋ฐ–์— ์—†์ŠตvalidTree
// ์•„๋ž˜ ํŒ๋ณ„์‹์„ ์ด์šฉํ•˜๋ฉด ์œ ํšจํ•˜์ง€ ์•Š์€ input์— ๋Œ€ํ•ด ์ƒ๋‹นํ•œ ์—ฐ์‚ฐ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
if len(edges) != n-1 {
return false
}
// ์ฃผ์–ด์ง„ 2์ฐจ์› ๋ฐฐ์—ด edges๋ฅผ ์ด์šฉํ•ด adjacency list๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค
adj := make([][]int, n)
for _, edge := range edges {
adj[edge[0]] = append(adj[edge[0]], edge[1])
adj[edge[1]] = append(adj[edge[1]], edge[0])
}
// cycle์ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด visited๋ผ๋Š” map์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค (Go์—์„œ๋Š” map์œผ๋กœ set ๊ธฐ๋Šฅ์„ ๋Œ€์‹ ํ•จ)
visited := make(map[int]bool)

var dfs func(int, int) bool
dfs = func(node int, parent int) bool {
// cycle ๋ฐœ๊ฒฌ์‹œ false return
if _, ok := visited[node]; ok {
return false
}
visited[node] = true
for _, next := range adj[node] {
if next == parent {
continue
}
if !dfs(next, node) {
return false
}
}
return true
}
// cycle ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค
if !dfs(0, -1) {
return false
}
// node๊ฐ€ ๋ชจ๋‘ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค
return len(visited) == n
}
89 changes: 89 additions & 0 deletions insert-interval/flynn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
ํ’€์ด
- newInterval์˜ start์™€ end์— ๋Œ€ํ•ด ๊ฐ๊ฐ ์ด์ง„ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•˜์—ฌ insertํ•  index๋ฅผ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
- index์˜ ์•ž๋’ค interval๊ณผ newInterval์„ ๋น„๊ตํ•˜์—ฌ merge ์—ฌ๋ถ€๋ฅผ ํŒ๋ณ„ํ•˜๋ฉด ๋ฌธ์ œ์—์„œ ์›ํ•˜๋Š” ๋ฐฐ์—ด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
Big O
- N: ์ฃผ์–ด์ง„ ๋ฐฐ์—ด intervals์˜ ๊ธธ์ด
- Time complexity: O(N)
- ์ด์ง„ ํƒ์ƒ‰ -> O(logN)
- append(res, ...) -> O(N)
- O(N + logN) = O(N)
- Space complexity: O(N)
- ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฐ์—ด res์˜ ๊ณต๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ณ ๋ คํ•˜๋ฉด O(N)
*/

func insert(intervals [][]int, newInterval []int) [][]int {
n := len(intervals)
// base case
if n == 0 {
return append(intervals, newInterval)
}
// ์ด์ง„ํƒ์ƒ‰ ํ•จ์ˆ˜
// isStart: newInterval์˜ start๋ฅผ ํƒ์ƒ‰ํ•  ๋• true, end๋ฅผ ํƒ์ƒ‰ํ•  ๋• false
// target๋ณด๋‹ค ํฐ ๊ฐ’ ์ค‘์—์„œ ๊ฐ€์žฅ ์ž‘์€ index๋ฅผ ๋ฐ˜ํ™˜ํ•จ
var binarySearch func(int, bool) int
binarySearch = func(target int, isStart bool) int {
lo := 0
hi := len(intervals)
for lo < hi {
mid := lo + (hi-lo)/2
if isStart {
if intervals[mid][0] < target {
lo = mid + 1
} else {
hi = mid
}
} else {
if intervals[mid][1] < target {
lo = mid + 1
} else {
hi = mid
}
}
}
return lo
}

start := binarySearch(newInterval[0], true)
// newInterval์˜ ์‹œ์ž‘ ์ง€์ ์ด intervals[start-1]์˜ ๋ ์ง€์ ๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด mergeํ•ด์•ผ ํ•จ
mergeStart := start > 0 && newInterval[0] <= intervals[start-1][1]
end := binarySearch(newInterval[1], false) - 1
// newInterval์˜ ๋ ์ง€์ ์ด intervals[end+1]์˜ ์‹œ์ž‘ ์ง€์ ๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด mergeํ•ด์•ผ ํ•จ
mergeEnd := end+1 < n && newInterval[1] >= intervals[end+1][0]

// -Go์—์„œ์˜ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค-
resCapacity := n + 1
if mergeStart {
resCapacity--
}
if mergeEnd {
resCapacity--
}
// -----------------------------
res := make([][]int, 0, resCapacity)
// newInterval์ด ๋“ค์–ด๊ฐˆ index๋ณด๋‹ค ์•ž ๋ถ€๋ถ„์˜ ๊ฐ’๋“ค์„ res์— append
if mergeStart {
res = append(res, intervals[:start-1]...)
} else {
res = append(res, intervals[:start]...)
}
// newInterval์„ res์— append
// mergeStart, mergeEnd ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ณ‘ํ•ฉํ• ์ง€ ๊ทธ๋Œ€๋กœ ๋„ฃ์„์ง€ ํŒ๋‹จ
if mergeStart && mergeEnd {
res = append(res, []int{intervals[start-1][0], intervals[end+1][1]})
} else if mergeStart {
res = append(res, []int{intervals[start-1][0], newInterval[1]})
} else if mergeEnd {
res = append(res, []int{newInterval[0], intervals[end+1][1]})
} else {
res = append(res, newInterval)
}
// newInterval์ด ๋“ค์–ด๊ฐˆ index๋ณด๋‹ค ๋’ท ๋ถ€๋ถ„์˜ ๊ฐ’๋“ค์„ res์— append
if mergeEnd {
res = append(res, intervals[end+2:]...)
} else {
res = append(res, intervals[end+1:]...)
}

return res
}
83 changes: 83 additions & 0 deletions maximum-depth-of-binary-tree/flynn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
ํ’€์ด
- DFS
Big O
- N: ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜
- H: ํŠธ๋ฆฌ์˜ ๋†’์ด
- Time complexity: O(N)
- ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค
- Space complexity: O(H)
- ์žฌ๊ท€ํ˜ธ์ถœ ์Šคํƒ์˜ ํฌ๊ธฐ๋Š” ํŠธ๋ฆฌ์˜ ๋†’์ด์— ๋น„๋ก€ํ•˜์—ฌ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค
*/

/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxDepth(root *TreeNode) int {
maxDepth := 0
var dig func(*TreeNode, int)
dig = func(node *TreeNode, depth int) {
if node == nil {
if maxDepth < depth {
maxDepth = depth
}
return
}
dig(node.Left, depth+1)
dig(node.Right, depth+1)
}
dig(root, 0)
return maxDepth
}

/*
ํ’€์ด
- BFS
Big O
- N: ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜
- Time complexity: O(N)
- ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค
- Space complexity: O(N)
- ๋…ธ๋“œ N๊ฐœ ์งœ๋ฆฌ ํŠธ๋ฆฌ์—์„œ ํ•œ ์ธต์˜ ํญ์€ N์„ ๋„˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
๋”ฐ๋ผ์„œ queue์˜ ๊ณต๊ฐ„๋ณต์žก๋„๋Š” O(N)์ž…๋‹ˆ๋‹ค
*/

/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxDepth(root *TreeNode) int {
level := 0
queue := make([]*TreeNode, 0)
if root != nil {
queue = append(queue, root)
level++
}
for len(queue) > 0 {
currQSize := len(queue)
for currQSize > 0 {
node := queue[0]
queue = queue[1:]
currQSize--
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
if len(queue) > 0 {
level++
}
}
return level
}
29 changes: 29 additions & 0 deletions reorder-list/flynn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reorderList(head *ListNode) {
// find a middle node
slow, fast := head, head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
// reverse the second part of the list
var prev, curr *ListNode = nil, slow
for curr != nil {
tmp := curr.Next
curr.Next = prev
prev = curr
curr = tmp
}
// merge two parts of the list
for curr1, curr2 := head, prev; curr2.Next != nil; {
tmp1, tmp2 := curr1.Next, curr2.Next
curr1.Next, curr2.Next = curr2, curr1.Next
curr1, curr2 = tmp1, tmp2
}
}

0 comments on commit c3ee69e

Please sign in to comment.