Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion lowest-common-ancestor-of-a-binary-search-tree/juhui-jeong.java
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Binary Search, Tree
  • 설명: 이 코드는 이진 탐색 트리의 특성을 활용하여 두 노드의 공통 조상을 찾는 문제로, 값 비교를 통해 탐색 범위를 좁히는 이진 탐색 패턴이 적용됩니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Solution.lowestCommonAncestor — Time: O(h) / Space: O(1)
복잡도
Time O(h)
Space O(1)

피드백: 트리의 높이 h에 비례하는 반복문을 통해, p와 q의 값에 따라 좌우로 내려가며 최적의 공통 조상을 찾는다. 최악의 경우 트리의 높이만큼 탐색하므로 O(h) 시간과 O(1) 공간이 소요된다.

개선 제안: 현재 구현이 적절해 보입니다.

풀이 2: Solution.lowestCommonAncestor — Time: O(h) / Space: O(h)
복잡도
Time O(h)
Space O(h)

피드백: 재귀 호출을 통해 트리의 높이만큼 호출 스택이 쌓이므로, 시간은 트리 높이 h에 비례하고 공간은 O(h)이다. p와 q의 값에 따라 좌우로 내려가며 최적의 공통 조상을 찾는다.

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
이전 풀이(반복문)
시간복잡도: O(log N)
공간복잡도: O(1)
*/

class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root != null) {
Expand All @@ -16,3 +17,19 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return null;
}
}
*/

/**
시간복잡도: O(h)
공간복잡도: O(h)
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (p.val < root.val && q.val < root.val) {
return this.lowestCommonAncestor(root.left, p, q);
} else if (p.val > root.val && q.val > root.val) {
return this.lowestCommonAncestor(root.right, p, q);
}
return root;
}
}
68 changes: 48 additions & 20 deletions non-overlapping-intervals/juhui-jeong.java
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Greedy, Sorting
  • 설명: 이 코드는 겹치지 않는 구간을 찾기 위해 정렬 후 탐욕적 선택을 하는 방식으로 해결하며, 정렬이 핵심 패턴입니다. 그리디 전략으로 최적의 선택을 합니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 3가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Solution.eraseOverlapIntervals — Time: O(n log n) / Space: O(1)
복잡도
Time O(n log n)
Space O(1)

피드백: intervals 배열을 정렬한 후, 겹치는 구간을 찾으며 최소 제거 횟수를 계산한다. 정렬이 시간 복잡도를 결정하며, 이후 반복문은 O(n)이다.

개선 제안: 현재 구현이 적절해 보입니다.

풀이 2: Solution.eraseOverlapIntervals — Time: O(n log n) / Space: O(1)
복잡도
Time O(n log n)
Space O(1)

피드백: 끝나는 시간 기준으로 정렬하여 겹치는 구간을 최소화한다. 정렬 후 반복문은 O(n)이며, 전체 시간 복잡도는 정렬에 의해 결정된다.

개선 제안: 현재 구현이 적절해 보입니다.

풀이 3: Solution.eraseOverlapIntervals — Time: ✅ O(n log n) → O(n log n) / Space: ❌ O(n) → O(1)
유저 분석 실제 분석 결과
Time O(n log n) O(n log n)
Space O(n) O(1)

피드백: 배열을 정렬한 후, 이전 종료 시간과 비교하여 겹침 여부를 판단한다. 정렬이 시간 복잡도를 지배하며, 반복문은 O(n)이다.

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Original file line number Diff line number Diff line change
@@ -1,51 +1,79 @@
/*
* 끝나는 시간 오름차순 정렬
*/
처음 풀이
시작 시간 기준 정렬
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, (a,b) -> Integer.compare(a[1], b[1]));
Arrays.sort(intervals, (a,b) -> {
if (a[0] != b[0]) return Integer.compare(a[0], b[0]);
return Integer.compare(a[1], b[1]);
});

int removeCntResult = 0;
int end = intervals[0][1];
int[] cur = intervals[0];

for (int i = 1; i< intervals.length; i++) {
if (intervals[i][0] < end) {
int [] next = intervals[i];

if (cur[1] > next[0]) {
removeCntResult += 1;
if (next[1] < cur[1]) {
cur = next;
}
} else {
end = intervals[i][1];
cur = next;
}
}
return removeCntResult;
}
}
*/


/*
처음 풀이
시작 시간 기준 정렬
* 끝나는 시간 오름차순 정렬

class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, (a,b) -> {
if (a[0] != b[0]) return Integer.compare(a[0], b[0]);
return Integer.compare(a[1], b[1]);
});
Arrays.sort(intervals, (a,b) -> Integer.compare(a[1], b[1]));

int removeCntResult = 0;
int[] cur = intervals[0];
int end = intervals[0][1];

for (int i = 1; i< intervals.length; i++) {
int [] next = intervals[i];

if (cur[1] > next[0]) {
if (intervals[i][0] < end) {
removeCntResult += 1;
if (next[1] < cur[1]) {
cur = next;
}
} else {
cur = next;
end = intervals[i][1];
}
}
return removeCntResult;
}
}
*/

/**
* 시간 복잡도: O(n log n)
* 공간 복잡도: O(n)
*/
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, (a,b) -> a[0] - b[0]);
int count = 0;
int prevEnd = intervals[0][1];

for (int i = 1; i < intervals.length; i++) {
int curStart = intervals[i][0];
int curEnd = intervals[i][1];

if (prevEnd <= curStart) {
// 안겹치는 경우(변경 없이 다음 배열로)
prevEnd = curEnd;
} else {
// 겹치는 경우
count++;
prevEnd = Math.min(prevEnd, curEnd);
}
}
return count;
}
}
61 changes: 46 additions & 15 deletions remove-nth-node-from-end-of-list/juhui-jeong.java
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Two Pointers
  • 설명: 두 포인터를 활용하여 리스트를 한 번 순회하며 n번째 노드를 찾고 제거하는 방식으로 효율적이다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Solution.removeNthFromEnd — Time: O(n) / Space: O(1)
복잡도
Time O(n)
Space O(1)

피드백: 더미 노드를 활용하여 fast와 slow 포인터를 n만큼 차이 나게 이동시킨 후, 동시에 이동하며 제거 위치를 찾는다. 시간은 리스트 길이 n에 비례하며, 공간은 상수이다.

개선 제안: 현재 구현이 적절해 보입니다.

풀이 2: Solution.removeNthFromEnd — Time: ✅ O(n) → O(n) / Space: ✅ O(1) → O(1)
유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(1) O(1)

피드백: 리스트 전체 길이를 먼저 계산한 후, 제거할 위치를 찾아서 노드를 연결한다. 두 번의 순회로 해결하며, 시간은 리스트 길이 n에 비례한다.

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@

/*
첫 번째 풀이
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
List<ListNode> list = new ArrayList<>();

while(head != null) {
list.add(head);
head = head.next;
}

list.remove(list.size()-n);
if (list.isEmpty()) return null;

for (int i = 0; i < list.size()-1; i++) {
list.get(i).next = list.get(i+1);
}
list.get(list.size()-1).next = null;
return list.get(0);
}
}
*/


/*
시간 복잡도: O(N)
공간 복잡도: O(1)
*/

class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
Expand All @@ -24,26 +49,32 @@ public ListNode removeNthFromEnd(ListNode head, int n) {
return dummy.next;
}
}
*/

/*
첫 번째 풀이
/**
*
* 시간 복잡도는 O(n)
* 공간 복잡도는 O(1)
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
List<ListNode> list = new ArrayList<>();

while(head != null) {
list.add(head);
head = head.next;
int length = 0;
ListNode curLenCheck = head;

while(curLenCheck != null) {
length++;
curLenCheck = curLenCheck.next;
}

list.remove(list.size()-n);
if (list.isEmpty()) return null;
int targetIndex = length - n;
if (targetIndex == 0) return head.next;

for (int i = 0; i < list.size()-1; i++) {
list.get(i).next = list.get(i+1);
ListNode targetPrev = head;
for (int i=0; i < targetIndex-1; i++) {
targetPrev = targetPrev.next;
}
list.get(list.size()-1).next = null;
return list.get(0);
targetPrev.next = targetPrev.next.next;

return head;
}
}
*/
30 changes: 30 additions & 0 deletions same-tree/juhui-jeong.java
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: DFS, BFS
  • 설명: 이 코드는 재귀를 이용한 깊이 우선 탐색(DFS)과 큐를 이용한 너비 우선 탐색(BFS) 방식을 모두 사용하여 두 트리의 노드 값을 비교하는 방식입니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Solution.isSameTree — Time: ✅ O(n) → O(n) / Space: ✅ O(h) → O(h)
유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(h) O(h)

피드백: 두 트리의 노드 값을 비교하며 재귀적으로 좌우 서브트리를 탐색한다. 모든 노드를 방문하므로 시간 복잡도는 O(n), 재귀 호출 스택은 트리 높이 h에 비례한다.

개선 제안: 현재 구현이 적절해 보입니다.

풀이 2: Solution.isSameTree — Time: ✅ O(n) → O(n) / Space: ✅ O(n) → O(n)
유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(n) O(n)

피드백: 두 트리를 레벨별로 큐를 이용해 비교한다. 모든 노드를 방문하므로 시간은 O(n), 큐의 크기는 최악의 경우 전체 노드 수에 비례한다.

개선 제안: 현재 구현이 적절해 보입니다.

Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,33 @@ public boolean isSameTree(TreeNode p, TreeNode q) {
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}

/*
* 시간 복잡도: O(n)
* 공간 복잡도: O(n)
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
Queue<TreeNode> queueP = new LinkedList<>();
Queue<TreeNode> queueQ = new LinkedList<>();

queueP.offer(p);
queueQ.offer(q);

while(!queueP.isEmpty() && !queueQ.isEmpty()) {
TreeNode curP = queueP.poll();
TreeNode curQ = queueQ.poll();

if (curP == null && curQ == null) continue;
if (curP == null || curQ == null) return false;

if (curP.val != curQ.val) return false;

queueP.offer(curP.left);
queueQ.offer(curQ.left);
queueP.offer(curP.right);
queueQ.offer(curQ.right);
}
return true;
}
}
43 changes: 43 additions & 0 deletions serialize-and-deserialize-binary-tree/juhui-jeong.java
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: DFS
  • 설명: 이 코드는 트리 구조를 재귀적으로 순회하며 직렬화와 역직렬화를 수행하는데, 깊이 우선 탐색(DFS) 방식을 사용하여 노드 방문 순서를 결정합니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Codec.serialize — Time: O(n) / Space: O(n)
복잡도
Time O(n)
Space O(n)

피드백: 트리의 모든 노드를 순회하며 문자열로 변환한다. 노드 수 n에 비례하는 시간과 공간이 소요된다.

개선 제안: 현재 구현이 적절해 보입니다.

풀이 2: Codec.deserialize — Time: O(n) / Space: O(n)
복잡도
Time O(n)
Space O(n)

피드백: 문자열을 배열로 분할 후 재귀적으로 노드를 복원한다. 노드 수 n에 비례하는 시간과 공간이 소요된다.

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

public class Codec {
private int index;

// Encodes a tree to a single string.(직렬화)
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
dfsSerialize(root, sb);
return sb.toString();
}

private void dfsSerialize(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append("null").append(",");
return;
}
sb.append(node.val).append(",");

dfsSerialize(node.left, sb);
dfsSerialize(node.right, sb);
}

// Decodes your encoded data to tree.(역직렬화)
public TreeNode deserialize(String data) {
String[] arr = data.split(",");
index = 0;
return dfsDeserialize(arr);
}

private TreeNode dfsDeserialize(String[] arr) {
String value = arr[index++];

if (value.equals("null")) {
return null;
}

TreeNode node = new TreeNode(Integer.parseInt(value));

node.left = dfsDeserialize(arr);
node.right = dfsDeserialize(arr);
return node;
}
}
Loading