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
27 changes: 27 additions & 0 deletions longest-substring-without-repeating-characters/JeonJe.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, Sliding Window, Hash Map / Hash Set
  • 설명: 왼쪽 포인터와 오른쪽 포인터를 이용해 부분 문자열의 중복 여부를 창 переп넘으로 관리하며, 창의 크기를 조정하는 Sliding Window 패턴이다. Set으로 중복 여부를 확인하며 두 포인터를 조정해 최장 부분문자열 길이를 갱신한다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(min(n, m)) O(k)

피드백: 왼쪽 포인터와 오른쪽 포인터를 이용한 대표적인 슬라이딩 윈도우 알고리즘으로 선형 시간에 동작한다. 중복을 제거하기 위해 해시셋을 사용한다.

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

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.

🏷️ 알고리즘 패턴 분석

longest-substring-without-repeating-characters/JeonJe.java
import java.util.*;

// TC: O(n)
// SC: O(min(n, m)) (m = 문자 집합 크기)
class Solution {
    public int lengthOfLongestSubstring(String s) {

        int answer = 0;
        int left = 0;

        Set<Character> temp = new HashSet<>();

        for (int right = 0; right < s.length(); right++) {

            // 중복이 사라질 때까지 s[left]를 set에서 빼며 left를 전진시킨다.
            while (temp.contains(s.charAt(right))) {
                temp.remove(s.charAt(left));
                left++;
            }

            temp.add(s.charAt(right));
            answer = Math.max(answer, right - left + 1);
        }

        return answer;
    }
}
  • 패턴: Two Pointers, Hash Map / Hash Set, Sliding Window
  • 설명: 두 포인터(left, right)로 창(window)을 확장/축소하며 중복 제거를 위해 해시셋으로 방문 여부를 추적한다. 창의 길이를 최대화하는 방식으로 부분 문자열 길이를 구하는 전형적인 Sliding Window 패턴이다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(min(n, m)) O(min(m, n))

피드백: 두 인덱스(left, right)로 창을 유지하며 각 문자를 집합에 담아 중복 여부를 검사합니다. 각 문자에 대해 한 번씩만 추가/삭제되므로 선형 시간 복잡도를 얻습니다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import java.util.*;

// TC: O(n)
// SC: O(min(n, m)) (m = 문자 집합 크기)
class Solution {
public int lengthOfLongestSubstring(String s) {

int answer = 0;
int left = 0;

Set<Character> temp = new HashSet<>();

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.

의미를 드러내는 네이밍 사용하시면 좋을 거 같습니다.


for (int right = 0; right < s.length(); right++) {

// 중복이 사라질 때까지 s[left]를 set에서 빼며 left를 전진시킨다.
while (temp.contains(s.charAt(right))) {
temp.remove(s.charAt(left));
left++;
}
Comment on lines +16 to +19

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.

각 문자의 인덱스를 저장해두면 중복 발생시 한 칸씩 옮기지 않아도 되서 최적화가 가능할 거 같습니다.


temp.add(s.charAt(right));
answer = Math.max(answer, right - left + 1);
}

return answer;
}
}
44 changes: 44 additions & 0 deletions number-of-islands/JeonJe.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.

🏷️ 알고리즘 패턴 분석

number-of-islands/JeonJe.java
import java.util.*;

// TC: O(m * n)
// SC: O(m * n)
class Solution {

    private static int[] dx = {0, -1, 0, 1};
    private static int[] dy = {1, 0, -1, 0};

    private int n = 0;
    private int m = 0;

    public int numIslands(char[][] grid) {
        n = grid[0].length;
        m = grid.length;

        boolean[][] visited = new boolean[m][n];

        int answer = 0;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (!visited[i][j] && grid[i][j] == '1') {
                    answer++;
                    dfs(i, j, grid, visited);
                }
            }
        }
        return answer;
    }

    private void dfs(int x, int y, char[][] grid, boolean[][] visited) {
        visited[x][y] = true;

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            if (0 <= nx && nx < m && 0 <= ny && ny < n && grid[nx][ny] == '1' && !visited[nx][ny]) {
                dfs(nx, ny, grid, visited);
            }
        }
    }
}
  • 패턴: Depth-First Search, Hash Map / Hash Set
  • 설명: 그리드에서 1로 연결된 영역을 DFS로 탐색하여 방문 처리하며 섹션마다 카운트를 증가시키는 풀이로, 인접 노드 탐색은 재귀를 이용합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(m * n) O(m*n)
Space O(m * n) O(m*n)

피드백: 그리드 모든 칸을 한 번씩 방문하며, 방문 여부를 boolean 배열로 추적합니다. DFS 재귀 대신 스택 사용 시 공간 사용이 달라질 수 있습니다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import java.util.*;

// TC: O(m * n)
// SC: O(m * n)
class Solution {

private static int[] dx = {0, -1, 0, 1};
private static int[] dy = {1, 0, -1, 0};

private int n = 0;
private int m = 0;

public int numIslands(char[][] grid) {
n = grid[0].length;
m = grid.length;
Comment on lines +3 to +15

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.

사소하지만 복잡도 표기는 m * n 인데 변수 순서는 n, m이라서 순서가 왜 바뀌어있지 생각이 들었습니다. for loop에서도 m부터 나와서 m, n 순서로 선언되면 좀 더 자연스러울 거 같은데 n, m 순서로 쓰신 이유가 있을까요?


boolean[][] visited = new boolean[m][n];

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.

in-place 마킹하는 방식도 고려하셨을 거 같은데 혹시 이 문제에서 visited 를 사용하신 이유가 있을까요?


int answer = 0;

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j] && grid[i][j] == '1') {
answer++;
dfs(i, j, grid, visited);
}
}
}
return answer;
}

private void dfs(int x, int y, char[][] grid, boolean[][] visited) {
visited[x][y] = true;

for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];

if (0 <= nx && nx < m && 0 <= ny && ny < n && grid[nx][ny] == '1' && !visited[nx][ny]) {
dfs(nx, ny, grid, visited);
}
}
}
}
19 changes: 19 additions & 0 deletions reverse-linked-list/JeonJe.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, Greedy, Linked List
  • 설명: 해당 코드는 단일 연결 리스트를 앞에서 뒤로 순회하며 포인터를 뒤집는 방식으로 노드를 역순으로 만듭니다. 두 개의 포인터를 사용해 각 노드의 방향을 바꾸는 일반적인 두 포인터(또는 해제 순서 관리) 기법에 해당합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(1) O(1)

피드백: 포인터 두 개(또는 세 개)만으로 노드의 연결 방향을 뒤집어 순회하며 처리한다.

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

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.

🏷️ 알고리즘 패턴 분석

reverse-linked-list/JeonJe.java
import java.util.*;

// TC: O(n)
// SC: O(1)
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;

        while (cur != null) {
            ListNode temp = cur.next;
            cur.next = prev;
            prev = cur;
            cur = temp;
        }

        return prev;
    }
}
  • 패턴: Two Pointers, Linked List
  • 설명: 링크드 리스트를 역순으로 뒤집는 대표적 기법으로, 포인터 두 개를 사용해 노드를 순회하며 방향을 바꿔나가는 방식입니다. 공간 복잡도 O(1)이며 흐름상 두 포인터를 교차시키는 형태로 구현됩니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(1) O(1)

피드백: 무엇보다 기존 포인터를 임시로 저장하여 역전시키는 표준 풀이로, 추가 공간 없이 한 번의 순회로 해결합니다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import java.util.*;

// TC: O(n)
// SC: O(1)
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode cur = head;

while (cur != null) {
ListNode temp = cur.next;
cur.next = prev;
prev = cur;
cur = temp;
}

return prev;
}
}
19 changes: 19 additions & 0 deletions unique-paths/JeonJe.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.

🏷️ 알고리즘 패턴 분석

unique-paths/JeonJe.java
import java.util.*;

// TC: O(m * n)
// SC: O(m * n)
class Solution {
    public int uniquePaths(int m, int n) {

        int[][] arr = new int[m][n];

        int upSide;
        int leftSide;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 && j == 0) {
                    arr[i][j] = 1;
                    continue;
                }

                upSide = i - 1 < 0 ? 0 : arr[i - 1][j];
                leftSide = j - 1 < 0 ? 0 : arr[i][j - 1];
                arr[i][j] = upSide + leftSide;
            }
        }

        return arr[m - 1][n - 1];
    }
}
  • 패턴: Dynamic Programming
  • 설명: 2차원 DP 배열을 사용해 좌상단에서 우하단까지의 경로 수를 누적 합으로 계산합니다. 각 위치의 값은 위쪽과 왼쪽의 경로 수의 합으로 결정되며, 중복 계산 없이 최적 부분구조를 이용합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(m * n) O(m*n)
Space O(m * n) O(m*n)

피드백: 각 셀의 값은 위의 셀과 왼쪽 셀의 합으로 계산되며, 경계 처리 시 0을 사용해 간단히 구현했다.

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

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.

🏷️ 알고리즘 패턴 분석

unique-paths/JeonJe.java
import java.util.*;

// TC: O(m * n)
// SC: O(n)
class Solution {
    public int uniquePaths(int m, int n) {

        int[] arr = new int[n];
        Arrays.fill(arr, 1);

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                arr[j] = arr[j] + arr[j - 1];
            }
        }

        return arr[n - 1];
    }
}
  • 패턴: Dynamic Programming, Greedy
  • 설명: 2차원 격자에서 시작점에서 도착점까지의 경로 수를 행렬로 계산하는 문제로, 한 줄 배열로 최적화하는 DP 기법을 사용합니다. 각 셀의 값은 위쪽과 왼쪽의 경로 수의 합으로 구성되며, 공간 복잡도를 줄이기 위해 1차원 배열로 구현합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(m * n) O(m * n)
Space O(n) O(n)

피드백: 각 행마다 현재 열의 값을 이전 열과 같은 행의 값을 이용해 갱신하여 메모리 사용을 최소화했다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import java.util.*;

// TC: O(m * n)
// SC: O(n)
class Solution {
public int uniquePaths(int m, int n) {

int[] arr = new int[n];
Arrays.fill(arr, 1);

for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
arr[j] = arr[j] + arr[j - 1];
}
}

return arr[n - 1];
}
}
Loading