From 0232e2bb321cdbcd19ca00ff66214cbb9ec22927 Mon Sep 17 00:00:00 2001 From: dongha kim Date: Fri, 7 Mar 2025 20:44:21 +0900 Subject: [PATCH] feat : week 13 --- find-median-from-data-stream/imsosleepy.java | 60 +++++++++++++++++++ insert-interval/imsosleepy.java | 37 ++++++++++++ kth-smallest-element-in-a-bst/imsosleepy.java | 26 ++++++++ .../imsosleepy.java | 18 ++++++ meeting-rooms/imsosleepy.java | 14 +++++ 5 files changed, 155 insertions(+) create mode 100644 find-median-from-data-stream/imsosleepy.java create mode 100644 insert-interval/imsosleepy.java create mode 100644 kth-smallest-element-in-a-bst/imsosleepy.java create mode 100644 lowest-common-ancestor-of-a-binary-search-tree/imsosleepy.java create mode 100644 meeting-rooms/imsosleepy.java diff --git a/find-median-from-data-stream/imsosleepy.java b/find-median-from-data-stream/imsosleepy.java new file mode 100644 index 000000000..611cbbab0 --- /dev/null +++ b/find-median-from-data-stream/imsosleepy.java @@ -0,0 +1,60 @@ +// 메모리초과로 알 수 있었던 것은 저장 공간이 여러개 필요하다는 거 였다. +// 그리고 주어진 데이터가 정렬되지 않아서 무조건 nlog(n) 이상의 시간복잡도가 나오기 때문에 +// 자동 정렬할 수 있는 우선순위 큐를 사용하면 좋겠따고 생각 +// 그러나 데이터를 나누는 알고리즘이 필요한지 모르고 헤메다가 GPT 답을 보게됨 +// 시간복잡도 우선순위 큐 : O(logN) +class MedianFinder { + private PriorityQueue maxHeap; + private PriorityQueue minHeap; + + public MedianFinder() { + maxHeap = new PriorityQueue<>(Collections.reverseOrder()); + minHeap = new PriorityQueue<>(); + } + + public void addNum(int num) { + maxHeap.offer(num); + + if (!minHeap.isEmpty() && maxHeap.peek() > minHeap.peek()) { + minHeap.offer(maxHeap.poll()); + } + + if (maxHeap.size() > minHeap.size() + 1) { + minHeap.offer(maxHeap.poll()); + } else if (minHeap.size() > maxHeap.size()) { + maxHeap.offer(minHeap.poll()); + } + } + + public double findMedian() { + if (maxHeap.size() > minHeap.size()) { + return maxHeap.peek(); + } else { + return (maxHeap.peek() + minHeap.peek()) / 2.0; + } + } +} + +// 메모리초과 +class MedianFinder { + private List arr; + + public MedianFinder() { + arr = new ArrayList<>(); + } + + public void addNum(int num) { + arr.add(num); + } + + public double findMedian() { + Collections.sort(arr); + + int size = arr.size(); + if (size % 2 == 1) { + return arr.get(size / 2); + } else { + return (arr.get(size / 2 - 1) + arr.get(size / 2)) / 2.0; + } + } +} diff --git a/insert-interval/imsosleepy.java b/insert-interval/imsosleepy.java new file mode 100644 index 000000000..d1e457963 --- /dev/null +++ b/insert-interval/imsosleepy.java @@ -0,0 +1,37 @@ +// start와 end라는 두개의 변수를 이용하면 한번만 순회해도 가능하다. +// 조건이 세개 밖에 없어서 단순하게 시뮬레이션 하면된다. +// (1) 현재 구간이 newInterval보다 앞에 있음 → 그대로 추가 +// (2) 현재 구간이 newInterval보다 뒤에 있음 → 병합할 필요 없음, 바로 추가 +// (3) 겹치는 경우 병합 +// 마지막 newInterval 추가 (병합된 상태일 수도 있음) << 이걸 못찾아서 너무 오래걸림 +// 시간복잡도 O(N) +class Solution { + public int[][] insert(int[][] intervals, int[] newInterval) { + List result = new ArrayList<>(); + int n = intervals.length; + int start = newInterval[0]; + int end = newInterval[1]; + + for (int i = 0; i < n; i++) { + + if (intervals[i][1] < start) { + result.add(intervals[i]); + } + + else if (intervals[i][0] > end) { + result.add(new int[]{start, end}); + start = intervals[i][0]; // 기존 구간부터 다시 추가 + end = intervals[i][1]; + } + + else { + start = Math.min(start, intervals[i][0]); + end = Math.max(end, intervals[i][1]); + } + } + + result.add(new int[]{start, end}); + + return result.toArray(new int[result.size()][]); + } +} diff --git a/kth-smallest-element-in-a-bst/imsosleepy.java b/kth-smallest-element-in-a-bst/imsosleepy.java new file mode 100644 index 000000000..005e753a6 --- /dev/null +++ b/kth-smallest-element-in-a-bst/imsosleepy.java @@ -0,0 +1,26 @@ +// 중위 순회로 맨아래까지 내려가서 순서를 찾는다. +// 시간 복잡도를 유지하면서 탐색할 방법을 몰라서 GPT로 찾아봤음. +// 한번만 탐색하므로 시간복잡도는 O(N) +class Solution { + int count = 0; + int result = 0; + + public int kthSmallest(TreeNode root, int k) { + inorder(root, k); + return result; + } + + private void inorder(TreeNode node, int k) { + if (node == null) return; + + inorder(node.left, k); + + count++; + if (count == k) { + result = node.val; + return; + } + + inorder(node.right, k); + } +} diff --git a/lowest-common-ancestor-of-a-binary-search-tree/imsosleepy.java b/lowest-common-ancestor-of-a-binary-search-tree/imsosleepy.java new file mode 100644 index 000000000..34495da6f --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/imsosleepy.java @@ -0,0 +1,18 @@ +// 백트래킹으로 만들려다 while문으로 전환 +// 문제만 봐선 아래에서 위로 가는 것 같지만, 이진 트리의 특성 상 루트보다 작으면 왼쪽, 크면 오른쪽으로 가면서 +// 주어 진 수인 p,q 를 찾을 수 있다. p가 q보다 클 수 도 있다. +// 한번만 순회하므로 O(N) +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + while (root != null) { + if (root.val > p.val && root.val > q.val) { + root = root.left; // 왼쪽으로 이동 + } else if (root.val < p.val && root.val < q.val) { + root = root.right; // 오른쪽으로 이동 + } else { + return root; + } + } + return null; + } +} diff --git a/meeting-rooms/imsosleepy.java b/meeting-rooms/imsosleepy.java new file mode 100644 index 000000000..97b71118f --- /dev/null +++ b/meeting-rooms/imsosleepy.java @@ -0,0 +1,14 @@ +// 정렬을 하지않으면 O(N^2), 정렬을 하면 최대 O(nlogn) 내에서 해결이 된다. +// 그래서 정렬 후 겹치는지 조회하는 방식 +public static boolean canAttendMeetings(int[][] intervals) { + if (intervals == null || intervals.length == 0) return true; + + Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0])); + + for (int i = 1; i < intervals.length; i++) { + if (intervals[i - 1][1] > intervals[i][0]) { + return false; + } + } + return true; +}