Skip to content

Commit

Permalink
Merge branch 'DaleStudy:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
wogha95 authored Nov 14, 2024
2 parents 13f0c08 + 76fb734 commit 0c7d92a
Show file tree
Hide file tree
Showing 74 changed files with 3,088 additions and 0 deletions.
67 changes: 67 additions & 0 deletions find-median-from-data-stream/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from heapq import heappush, heappop
from unittest import TestCase, main


class MedianFinder:
"""
Runtime: 137 ms (Beats 56.16%)
Time Complexity:
1) addNum
- 최악의 경우 heappush + (heappop + heappush) + (heappop + heapppush) 가 발생할 수 있으므로 O(5 * log n)
> O(5 * log n) ~= O(log n)
2) findMedian
> heap의 루트 값을 가지고 사칙연산만 하므로 O(1)
Memory: 39.94 MB (Beats 5.85%)
Space Complexity: O(n)
- max_heap은 최대 n // 2 개 혹은 n // 2 + 1개의 원소를 가지므로 O(n / 2 + 1), upper bound
- min_heap은 최대 n // 2개의 원소를 가지므로 O(n / 2)
> O(n / 2 + 1) + O(n / 2) ~= O(n) + O(n) ~= O(n)
"""

def __init__(self):
self.max_heap = []
self.min_heap = []

def addNum(self, num):
heappush(self.max_heap, -num)
if self.min_heap and (-self.max_heap[0] > self.min_heap[0]):
heappush(self.min_heap, -heappop(self.max_heap))

if len(self.max_heap) > len(self.min_heap) + 1:
heappush(self.min_heap, -heappop(self.max_heap))
elif len(self.max_heap) < len(self.min_heap):
heappush(self.max_heap, -heappop(self.min_heap))

def findMedian(self):
if self.max_heap and self.min_heap:
if len(self.max_heap) == len(self.min_heap):
return ((-self.max_heap[0]) + self.min_heap[0]) / 2
else:
return -self.max_heap[0]
elif self.min_heap and not self.max_heap:
return self.min_heap[0]
elif not self.min_heap and self.max_heap:
return -self.max_heap[0]
else:
return 0.0


class _LeetCodeTestCases(TestCase):

def test_1(self):
medianFinder = MedianFinder()
medianFinder.addNum(-1)
self.assertEqual(medianFinder.findMedian(), -1.0)
medianFinder.addNum(-2)
self.assertEqual(medianFinder.findMedian(), -1.5)
medianFinder.addNum(-3)
self.assertEqual(medianFinder.findMedian(), -2.0)
medianFinder.addNum(-4)
self.assertEqual(medianFinder.findMedian(), -2.5)
medianFinder.addNum(-5)
self.assertEqual(medianFinder.findMedian(), -3.0)


if __name__ == '__main__':
main()
164 changes: 164 additions & 0 deletions find-median-from-data-stream/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/**
* https://leetcode.com/problems/find-median-from-data-stream
* array with binary search
*/
class MedianFinder {
// S.C. O(n)
private nums: number[] = [];

// T.C. O(n)
addNum(num: number): void {
if (this.nums.length === 0) {
this.nums.push(num);
return;
} else {
this.putNumWithBinarySearch(num);
}
}

private putNumWithBinarySearch(num: number): void {
let left = 0;
let right = this.nums.length - 1;

while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (this.nums[mid] === num) {
this.nums.splice(mid, 0, num);
return;
} else if (this.nums[mid] < num) {
left = mid + 1;
} else {
right = mid - 1;
}
}

// T.C. O(n)
this.nums.splice(left, 0, num);
}

// T.C. O(1)
findMedian(): number {
const len = this.nums.length;

if (len % 2 === 1) {
return this.nums[Math.floor(len / 2)];
} else {
return (this.nums[len / 2] + this.nums[len / 2 - 1]) / 2;
}
}
}

/**
* heap...
* TL;DR
*/
class MedianFinder {
// S.C. O(n)
private smallHalf: MaxHeap = new MaxHeap();
private largeHalf: MinHeap = new MinHeap();

// T.C. O(log n)
addNum(num: number): void {
this.smallHalf.push(num);
this.largeHalf.push(this.smallHalf.pop()!);

if (this.smallHalf.size() < this.largeHalf.size()) {
this.smallHalf.push(this.largeHalf.pop()!);
}
}

// T.C. O(1)
findMedian(): number {
if (this.smallHalf.size() === this.largeHalf.size()) {
return (this.smallHalf.peek()! + this.largeHalf.peek()!) / 2;
} else {
return this.smallHalf.peek()!;
}
}
}

class MinHeap {
protected heap: number[] = [];

push(val: number): void {
this.heap.push(val);
this.heapifyUp();
}

pop(): number | undefined {
if (this.heap.length === 0) return undefined;
if (this.heap.length === 1) return this.heap.pop();

const result = this.heap[0];
this.heap[0] = this.heap.pop()!;
this.heapifyDown();
return result;
}

peek(): number | undefined {
return this.heap[0];
}

size(): number {
return this.heap.length;
}

private heapifyUp(): void {
let index = this.heap.length - 1;
while (index > 0) {
const parentIndex = Math.floor((index - 1) / 2);
if (this.heap[parentIndex] <= this.heap[index]) break;

this.swap(parentIndex, index);
index = parentIndex;
}
}

private heapifyDown(): void {
let index = 0;
while (true) {
let smallest = index;
const leftChild = 2 * index + 1;
const rightChild = 2 * index + 2;

if (
leftChild < this.heap.length &&
this.heap[leftChild] < this.heap[smallest]
) {
smallest = leftChild;
}

if (
rightChild < this.heap.length &&
this.heap[rightChild] < this.heap[smallest]
) {
smallest = rightChild;
}

if (smallest === index) break;

this.swap(index, smallest);
index = smallest;
}
}

protected swap(i: number, j: number): void {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}
}

class MaxHeap extends MinHeap {
push(val: number): void {
super.push(-val);
}

pop(): number | undefined {
const val = super.pop();
return val === undefined ? undefined : -val;
}

peek(): number | undefined {
const val = super.peek();
return val === undefined ? undefined : -val;
}
}
67 changes: 67 additions & 0 deletions find-median-from-data-stream/flynn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
풀이
- 이진탐색을 이용합니다
Big O
- N: 현재 MedianFinder.nums의 크기
- AddNum
- Time complexity: O(N)
- bisect -> O(logN)
- slices.Insert -> O(N)
- Space complexity: O(1)
- FindMedian
- Time complexity: O(1)
- Space complexity: O(1)
*/

import "slices"

type MedianFinder struct {
nums []int
}

func Constructor() MedianFinder {
mf := MedianFinder{}
mf.nums = make([]int, 0)
return mf
}

func (this *MedianFinder) AddNum(num int) {
n := len(this.nums)
if n == 0 {
this.nums = append(this.nums, num)
} else {
idx := bisectLeft(this.nums, num)
this.nums = slices.Insert(this.nums, idx, num)
}
}

func (this *MedianFinder) FindMedian() float64 {
n := len(this.nums)
if n%2 == 0 {
return (float64(this.nums[n/2-1]) + float64(this.nums[n/2])) / 2
} else {
return float64(this.nums[n/2])
}
}

// ----- Helper -----
func bisectLeft(arr []int, x int) int {
lo := 0
hi := len(arr)
for lo < hi {
mid := lo + (hi-lo)/2
if arr[mid] < x {
lo = mid + 1
} else {
hi = mid
}
}
return lo
}

/**
* Your MedianFinder object will be instantiated and called as such:
* obj := Constructor();
* obj.AddNum(num);
* param_2 := obj.FindMedian();
*/
42 changes: 42 additions & 0 deletions house-robber/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import List
from unittest import TestCase, main


class Solution:
def rob(self, nums: List[int]) -> int:
return self.solve_dp(nums)

"""
Runtime: 0 ms (Beats 100.00%)
Time Complexity: O(n)
- nums 배열을 조회하며 dp 배열을 갱신하므로 O(n)
- 2항에 대한 max 연산을 사용하므로 * O(2)
> O(2 * n) ~= O(n)
Memory: 16.62 MB (Beats 24.05%)
Space Complexity: O(n)
> 길이가 n인 dp 배열을 사용하므로 O(n)
"""

def solve_dp(self, nums: List[int]) -> int:
if len(nums) <= 2:
return max(nums)

dp = [0] * len(nums)
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, len(nums)):
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])

return dp[-1]


class _LeetCodeTestCases(TestCase):
def test_1(self):
nums = [2,1,1,2]
output = 4
self.assertEqual(Solution().rob(nums), output)


if __name__ == '__main__':
main()
15 changes: 15 additions & 0 deletions house-robber/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* https://leetcode.com/problems/house-robber
* T.C. O(n)
* S.C. O(1)
*/
function rob(nums: number[]): number {
let prev = 0;
let curr = 0;
for (let i = 0; i < nums.length; i++) {
const temp = curr;
curr = Math.max(prev + nums[i], curr);
prev = temp;
}
return curr;
}
21 changes: 21 additions & 0 deletions house-robber/TonyKim9401.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// TC: O(n)
// always need to check every case
// SC: O(n)
// the length of the result int list is same with the length of the given nums int list
class Solution {
public int rob(int[] nums) {
int[] result = new int[nums.length];

if (nums.length < 2) return nums[0];
if (nums.length < 3) return Math.max(nums[0], nums[1]);

result[0] = nums[0];
result[1] = Math.max(nums[0], nums[1]);

for (int i = 2; i < nums.length; i++) {
result[i] = Math.max(result[i - 1], result[i - 2] + nums[i]);
}

return result[nums.length-1];
}
}
Loading

0 comments on commit 0c7d92a

Please sign in to comment.