Skip to content

Commit 0c7d92a

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 13f0c08 + 76fb734 commit 0c7d92a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+3088
-0
lines changed

find-median-from-data-stream/EGON.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from heapq import heappush, heappop
2+
from unittest import TestCase, main
3+
4+
5+
class MedianFinder:
6+
"""
7+
Runtime: 137 ms (Beats 56.16%)
8+
Time Complexity:
9+
1) addNum
10+
- 최악의 경우 heappush + (heappop + heappush) + (heappop + heapppush) 가 발생할 수 있으므로 O(5 * log n)
11+
> O(5 * log n) ~= O(log n)
12+
2) findMedian
13+
> heap의 루트 값을 가지고 사칙연산만 하므로 O(1)
14+
15+
Memory: 39.94 MB (Beats 5.85%)
16+
Space Complexity: O(n)
17+
- max_heap은 최대 n // 2 개 혹은 n // 2 + 1개의 원소를 가지므로 O(n / 2 + 1), upper bound
18+
- min_heap은 최대 n // 2개의 원소를 가지므로 O(n / 2)
19+
> O(n / 2 + 1) + O(n / 2) ~= O(n) + O(n) ~= O(n)
20+
"""
21+
22+
def __init__(self):
23+
self.max_heap = []
24+
self.min_heap = []
25+
26+
def addNum(self, num):
27+
heappush(self.max_heap, -num)
28+
if self.min_heap and (-self.max_heap[0] > self.min_heap[0]):
29+
heappush(self.min_heap, -heappop(self.max_heap))
30+
31+
if len(self.max_heap) > len(self.min_heap) + 1:
32+
heappush(self.min_heap, -heappop(self.max_heap))
33+
elif len(self.max_heap) < len(self.min_heap):
34+
heappush(self.max_heap, -heappop(self.min_heap))
35+
36+
def findMedian(self):
37+
if self.max_heap and self.min_heap:
38+
if len(self.max_heap) == len(self.min_heap):
39+
return ((-self.max_heap[0]) + self.min_heap[0]) / 2
40+
else:
41+
return -self.max_heap[0]
42+
elif self.min_heap and not self.max_heap:
43+
return self.min_heap[0]
44+
elif not self.min_heap and self.max_heap:
45+
return -self.max_heap[0]
46+
else:
47+
return 0.0
48+
49+
50+
class _LeetCodeTestCases(TestCase):
51+
52+
def test_1(self):
53+
medianFinder = MedianFinder()
54+
medianFinder.addNum(-1)
55+
self.assertEqual(medianFinder.findMedian(), -1.0)
56+
medianFinder.addNum(-2)
57+
self.assertEqual(medianFinder.findMedian(), -1.5)
58+
medianFinder.addNum(-3)
59+
self.assertEqual(medianFinder.findMedian(), -2.0)
60+
medianFinder.addNum(-4)
61+
self.assertEqual(medianFinder.findMedian(), -2.5)
62+
medianFinder.addNum(-5)
63+
self.assertEqual(medianFinder.findMedian(), -3.0)
64+
65+
66+
if __name__ == '__main__':
67+
main()
+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* https://leetcode.com/problems/find-median-from-data-stream
3+
* array with binary search
4+
*/
5+
class MedianFinder {
6+
// S.C. O(n)
7+
private nums: number[] = [];
8+
9+
// T.C. O(n)
10+
addNum(num: number): void {
11+
if (this.nums.length === 0) {
12+
this.nums.push(num);
13+
return;
14+
} else {
15+
this.putNumWithBinarySearch(num);
16+
}
17+
}
18+
19+
private putNumWithBinarySearch(num: number): void {
20+
let left = 0;
21+
let right = this.nums.length - 1;
22+
23+
while (left <= right) {
24+
const mid = Math.floor((left + right) / 2);
25+
if (this.nums[mid] === num) {
26+
this.nums.splice(mid, 0, num);
27+
return;
28+
} else if (this.nums[mid] < num) {
29+
left = mid + 1;
30+
} else {
31+
right = mid - 1;
32+
}
33+
}
34+
35+
// T.C. O(n)
36+
this.nums.splice(left, 0, num);
37+
}
38+
39+
// T.C. O(1)
40+
findMedian(): number {
41+
const len = this.nums.length;
42+
43+
if (len % 2 === 1) {
44+
return this.nums[Math.floor(len / 2)];
45+
} else {
46+
return (this.nums[len / 2] + this.nums[len / 2 - 1]) / 2;
47+
}
48+
}
49+
}
50+
51+
/**
52+
* heap...
53+
* TL;DR
54+
*/
55+
class MedianFinder {
56+
// S.C. O(n)
57+
private smallHalf: MaxHeap = new MaxHeap();
58+
private largeHalf: MinHeap = new MinHeap();
59+
60+
// T.C. O(log n)
61+
addNum(num: number): void {
62+
this.smallHalf.push(num);
63+
this.largeHalf.push(this.smallHalf.pop()!);
64+
65+
if (this.smallHalf.size() < this.largeHalf.size()) {
66+
this.smallHalf.push(this.largeHalf.pop()!);
67+
}
68+
}
69+
70+
// T.C. O(1)
71+
findMedian(): number {
72+
if (this.smallHalf.size() === this.largeHalf.size()) {
73+
return (this.smallHalf.peek()! + this.largeHalf.peek()!) / 2;
74+
} else {
75+
return this.smallHalf.peek()!;
76+
}
77+
}
78+
}
79+
80+
class MinHeap {
81+
protected heap: number[] = [];
82+
83+
push(val: number): void {
84+
this.heap.push(val);
85+
this.heapifyUp();
86+
}
87+
88+
pop(): number | undefined {
89+
if (this.heap.length === 0) return undefined;
90+
if (this.heap.length === 1) return this.heap.pop();
91+
92+
const result = this.heap[0];
93+
this.heap[0] = this.heap.pop()!;
94+
this.heapifyDown();
95+
return result;
96+
}
97+
98+
peek(): number | undefined {
99+
return this.heap[0];
100+
}
101+
102+
size(): number {
103+
return this.heap.length;
104+
}
105+
106+
private heapifyUp(): void {
107+
let index = this.heap.length - 1;
108+
while (index > 0) {
109+
const parentIndex = Math.floor((index - 1) / 2);
110+
if (this.heap[parentIndex] <= this.heap[index]) break;
111+
112+
this.swap(parentIndex, index);
113+
index = parentIndex;
114+
}
115+
}
116+
117+
private heapifyDown(): void {
118+
let index = 0;
119+
while (true) {
120+
let smallest = index;
121+
const leftChild = 2 * index + 1;
122+
const rightChild = 2 * index + 2;
123+
124+
if (
125+
leftChild < this.heap.length &&
126+
this.heap[leftChild] < this.heap[smallest]
127+
) {
128+
smallest = leftChild;
129+
}
130+
131+
if (
132+
rightChild < this.heap.length &&
133+
this.heap[rightChild] < this.heap[smallest]
134+
) {
135+
smallest = rightChild;
136+
}
137+
138+
if (smallest === index) break;
139+
140+
this.swap(index, smallest);
141+
index = smallest;
142+
}
143+
}
144+
145+
protected swap(i: number, j: number): void {
146+
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
147+
}
148+
}
149+
150+
class MaxHeap extends MinHeap {
151+
push(val: number): void {
152+
super.push(-val);
153+
}
154+
155+
pop(): number | undefined {
156+
const val = super.pop();
157+
return val === undefined ? undefined : -val;
158+
}
159+
160+
peek(): number | undefined {
161+
const val = super.peek();
162+
return val === undefined ? undefined : -val;
163+
}
164+
}

find-median-from-data-stream/flynn.go

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
풀이
3+
- 이진탐색을 이용합니다
4+
Big O
5+
- N: 현재 MedianFinder.nums의 크기
6+
- AddNum
7+
- Time complexity: O(N)
8+
- bisect -> O(logN)
9+
- slices.Insert -> O(N)
10+
- Space complexity: O(1)
11+
- FindMedian
12+
- Time complexity: O(1)
13+
- Space complexity: O(1)
14+
*/
15+
16+
import "slices"
17+
18+
type MedianFinder struct {
19+
nums []int
20+
}
21+
22+
func Constructor() MedianFinder {
23+
mf := MedianFinder{}
24+
mf.nums = make([]int, 0)
25+
return mf
26+
}
27+
28+
func (this *MedianFinder) AddNum(num int) {
29+
n := len(this.nums)
30+
if n == 0 {
31+
this.nums = append(this.nums, num)
32+
} else {
33+
idx := bisectLeft(this.nums, num)
34+
this.nums = slices.Insert(this.nums, idx, num)
35+
}
36+
}
37+
38+
func (this *MedianFinder) FindMedian() float64 {
39+
n := len(this.nums)
40+
if n%2 == 0 {
41+
return (float64(this.nums[n/2-1]) + float64(this.nums[n/2])) / 2
42+
} else {
43+
return float64(this.nums[n/2])
44+
}
45+
}
46+
47+
// ----- Helper -----
48+
func bisectLeft(arr []int, x int) int {
49+
lo := 0
50+
hi := len(arr)
51+
for lo < hi {
52+
mid := lo + (hi-lo)/2
53+
if arr[mid] < x {
54+
lo = mid + 1
55+
} else {
56+
hi = mid
57+
}
58+
}
59+
return lo
60+
}
61+
62+
/**
63+
* Your MedianFinder object will be instantiated and called as such:
64+
* obj := Constructor();
65+
* obj.AddNum(num);
66+
* param_2 := obj.FindMedian();
67+
*/

house-robber/EGON.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import List
2+
from unittest import TestCase, main
3+
4+
5+
class Solution:
6+
def rob(self, nums: List[int]) -> int:
7+
return self.solve_dp(nums)
8+
9+
"""
10+
Runtime: 0 ms (Beats 100.00%)
11+
Time Complexity: O(n)
12+
- nums 배열을 조회하며 dp 배열을 갱신하므로 O(n)
13+
- 2항에 대한 max 연산을 사용하므로 * O(2)
14+
> O(2 * n) ~= O(n)
15+
16+
Memory: 16.62 MB (Beats 24.05%)
17+
Space Complexity: O(n)
18+
> 길이가 n인 dp 배열을 사용하므로 O(n)
19+
"""
20+
21+
def solve_dp(self, nums: List[int]) -> int:
22+
if len(nums) <= 2:
23+
return max(nums)
24+
25+
dp = [0] * len(nums)
26+
dp[0] = nums[0]
27+
dp[1] = max(nums[0], nums[1])
28+
for i in range(2, len(nums)):
29+
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])
30+
31+
return dp[-1]
32+
33+
34+
class _LeetCodeTestCases(TestCase):
35+
def test_1(self):
36+
nums = [2,1,1,2]
37+
output = 4
38+
self.assertEqual(Solution().rob(nums), output)
39+
40+
41+
if __name__ == '__main__':
42+
main()

house-robber/HC-kang.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* https://leetcode.com/problems/house-robber
3+
* T.C. O(n)
4+
* S.C. O(1)
5+
*/
6+
function rob(nums: number[]): number {
7+
let prev = 0;
8+
let curr = 0;
9+
for (let i = 0; i < nums.length; i++) {
10+
const temp = curr;
11+
curr = Math.max(prev + nums[i], curr);
12+
prev = temp;
13+
}
14+
return curr;
15+
}

house-robber/TonyKim9401.java

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// TC: O(n)
2+
// always need to check every case
3+
// SC: O(n)
4+
// the length of the result int list is same with the length of the given nums int list
5+
class Solution {
6+
public int rob(int[] nums) {
7+
int[] result = new int[nums.length];
8+
9+
if (nums.length < 2) return nums[0];
10+
if (nums.length < 3) return Math.max(nums[0], nums[1]);
11+
12+
result[0] = nums[0];
13+
result[1] = Math.max(nums[0], nums[1]);
14+
15+
for (int i = 2; i < nums.length; i++) {
16+
result[i] = Math.max(result[i - 1], result[i - 2] + nums[i]);
17+
}
18+
19+
return result[nums.length-1];
20+
}
21+
}

0 commit comments

Comments
 (0)