From 3b448ca946f9472948e55cbb1ad078ce9b3e30ac Mon Sep 17 00:00:00 2001 From: ohchansol Date: Sat, 27 Dec 2025 20:40:23 +0900 Subject: [PATCH 1/7] feat: reverse bits --- reverse-bits/haxr369.java | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 reverse-bits/haxr369.java diff --git a/reverse-bits/haxr369.java b/reverse-bits/haxr369.java new file mode 100644 index 0000000000..3bed7170df --- /dev/null +++ b/reverse-bits/haxr369.java @@ -0,0 +1,45 @@ +class Solution { + /** + * Runtime: 1 ms (Beats 54.22%) + * Memory: 42.34 MB (Beats 63.68%) + * Space Complexity: O(1) + * > 고정된 32byte 배열 사용으로 O(1) + * Time Complexity: O(logN) + * - n의 2진수 변환 => O(logN) + * - 32bit 역순 변환 => O(1) + * > O(log32) + O(1) => O(log32) 사실상 O(1) + * + */ + public int reverseBits(int n) { + byte[] binarys = new byte[32]; + int temp = n; + + // n의 2진수를 저장하기 + int i = 0; + while (temp > 0) { // 최종 0이되면 종료 + // 짝수인 경우 i번째 비트는 0 + if (temp % 2 == 0) { + binarys[i] = 0; + } else { // 홀수면 i번째 비트는 1 + binarys[i] = 1; + temp -= 1; + } + temp = temp / 2; + i++; // 비트수 올리기 + } + + // 저장된 비트를 역순으로 십진수로 변환하기 + int ans = 0; // 총합산 + int base = 1; // i-j번째 2진수 값 + int j = 0; + while (31 >= j) { + // 2진수가 1인 경우만 합산한다. + if (binarys[31 - j] == 1) { + ans += base; + } + base *= 2; + j++; + } + return ans; + } +} From 4a0f4371d32c10c1e2af6bea80c7c9ef4ccd308a Mon Sep 17 00:00:00 2001 From: ohchansol Date: Mon, 29 Dec 2025 16:15:10 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20longest-repeating-character-replace?= =?UTF-8?q?ment=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haxr369.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 longest-repeating-character-replacement/haxr369.java diff --git a/longest-repeating-character-replacement/haxr369.java b/longest-repeating-character-replacement/haxr369.java new file mode 100644 index 0000000000..2c2ff27426 --- /dev/null +++ b/longest-repeating-character-replacement/haxr369.java @@ -0,0 +1,81 @@ +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Runtime: 105 ms (Beats 5.05%) + * Memory: 46.94 MB (Beats 25.55%) + * Space Complexity: O(1) + * > 26개 영문자에 대한 Hash 테이블 => O(26) => O(1) + * Time Complexity: O(N) + * - 윈도우를 문자열 길이만큼 이동시키기 => O(N) + * - 윈도우 변경할 때마다 최소변경필요개수 구하기 => O(26) => O(1) + * > O(N)xO(1) => O(N) + * + */ +class Solution { + /** + * 슬라이딩 윈도우 기법 사용 + * + * 1. 시작인덱스, 종료인덱스 설정. + * 2. 윈도우 안에 변경 필요 건수가 k 보다 크면 시작인덱스 늘리기 => 변환할 수 없기 때문에 + * 3. 만약 변경 필요 건수가 k와 작거나 같다면 종료인덱스 늘리기 => 변환 가능한 유효한 문자열이기 때문 + */ + public int characterReplacement(String s, int k) { + int strIdx = 0; + int endIdx = 0; + int visited = -1; // visited 문자까지는 윈도우에 들어갔기 때문에 넣지 않는다. + int ans = 0; + + // 윈도우 상태 관리 + Map winState = new HashMap<>(); + + while (s.length() > endIdx) { + + // endC를 윈도우에 추가하기 + if (visited < endIdx) { // 두번 넣지 않게 방어막 쳐주기 + Character endC = Character.valueOf(s.charAt(endIdx)); + int temp = winState.getOrDefault(endC, 0); + winState.put(endC, temp + 1); + visited++; + } + + // 유효성 검사하기 O(26) + int minChng = cntMinChng(winState, endIdx - strIdx + 1); + if (minChng <= k) { // 유효한 상태 + ans = Integer.max(ans, endIdx - strIdx + 1); + endIdx++; + } else { // 유효하지 않은 상태 + Character strC = Character.valueOf(s.charAt(strIdx)); + // 뒷자리 하나 빼기 + int temp = winState.getOrDefault(strC, 0); + winState.put(strC, temp - 1); + strIdx++; + } + } + return ans; + } + + /** + * 시간복잡도 => O(26) + * 윈도우에서 최소변경필요개수 카운트 + * 변경해야할 최소 값 = 현재 윈도우 길이 - (가장 많이 등장한 문자 개수) + */ + private int cntMinChng(Map winState, int winLen) { + int minChng = Integer.MAX_VALUE; + Iterator> it = winState.entrySet().iterator(); + // 비어 있다면 0개로 출력 + if (!it.hasNext()) { + return 0; + } + + // 뭔가 있으면 돌리기 + while (it.hasNext()) { + Map.Entry entry = it.next(); + int v = entry.getValue(); + int chng = winLen - v; + minChng = Integer.min(chng, minChng); + } + return minChng; + } +} From d4b7d87a46aa3b427fc90b8f7702f7cee9464fed Mon Sep 17 00:00:00 2001 From: ohchansol Date: Sat, 3 Jan 2026 00:04:06 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20clone-graph=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clone-graph/haxr369.java | 90 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 clone-graph/haxr369.java diff --git a/clone-graph/haxr369.java b/clone-graph/haxr369.java new file mode 100644 index 0000000000..0416fee146 --- /dev/null +++ b/clone-graph/haxr369.java @@ -0,0 +1,90 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Runtime: 25 ms (Beats 72.12%) + * Memory: 44.35 MB (Beats 34.32%) + * Space Complexity: O(N) + * - 모든 노드 저장 => O(N) + * - visited로 복사했던 노드 관리 => O(N) + * > O(N) + * Time Complexity: O(N) + * - 루트노드부터 모든 노드까지 한번씩 탐색 => O(N) + * > O(N) + * + */ + +class Node { + public int val; + public List neighbors; + + public Node() { + val = 0; + neighbors = new ArrayList(); + } + + public Node(int _val) { + val = _val; + neighbors = new ArrayList(); + } + + public Node(int _val, ArrayList _neighbors) { + val = _val; + neighbors = _neighbors; + } +} + +class Solution { + public Node cloneGraph(Node node) { + if (node == null) { + return node; + } + + if (node.neighbors == null) { + Node newNode = new Node(node.val, null); + return newNode; + } else if (node.neighbors.isEmpty()) { + Node newNode = new Node(node.val, new ArrayList<>()); + return newNode; + } + + Node[] visited = new Node[104]; + + Node ans = new Node(node.val, new ArrayList<>(node.neighbors)); + visited[ans.val] = ans; + dfs(ans, visited); + + return ans; + } + + /** + * node의 리스트를 dfs로 변경해간다. + * 다만, 변경했던 노드는 다시 변경하지 않음 + */ + private void dfs(Node node, Node[] visited) { + + List neighbors = node.neighbors; // 이전 것 + + List newNeighbors = new ArrayList<>(); // 새 껍질 + // 하나씩 새걸로 바꾸자 + for (Node n : neighbors) { + if (visited[n.val] != null) { + newNeighbors.add(visited[n.val]); + continue; + } + Node newN = new Node(n.val, new ArrayList<>(n.neighbors)); // 껍질 만들기 + visited[newN.val] = newN; + dfs(newN, visited); // + newNeighbors.add(newN); + } + node.neighbors = newNeighbors; // 신규 리스트로 바꿔치기 + // printNode(node); + } + + private void printNode(Node node) { + System.out.print("val -> " + node.val); + System.out.println(" size -> " + node.neighbors.size()); + node.neighbors.forEach(n -> System.out.print(n.val)); + System.out.print('\n'); + } +} From 169b91ca6019d3cbd1af2ac1d55d630a2e05bc36 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Sat, 3 Jan 2026 13:27:51 +0900 Subject: [PATCH 4/7] feat: linked-list-cycle sovle --- linked-list-cycle/Solution.java | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 linked-list-cycle/Solution.java diff --git a/linked-list-cycle/Solution.java b/linked-list-cycle/Solution.java new file mode 100644 index 0000000000..143b696bc9 --- /dev/null +++ b/linked-list-cycle/Solution.java @@ -0,0 +1,37 @@ + +class ListNode { + int val; + ListNode next; + + ListNode(int x) { + val = x; + next = null; + } +} + +public class Solution { + + /** + * floyd 알고리즘(토끼 거북) 알고리즘 사용해서 + * 무한한 순환을 찾기 + */ + public boolean hasCycle(ListNode head) { + if (head == null) + return false; + + ListNode rb = head; + ListNode tt = head; + // 토끼와 거북이의 주소가 동일할 때까지 탐색하기 + while (rb.next != null && rb.next.next != null) { + // 토끼는 두 노드씩 이동하기 + rb = rb.next.next; + // 거북이는 한 노드씩 이동하기 + tt = tt.next; + if (rb == tt) { + // System.out.println("토끼("+rb.val+")와 거북이("+tt.val+")가 만났음"); + return true; + } + } + return false; + } +} From fb3b280027c61c3210436d1757e48df8b24d7892 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Sat, 3 Jan 2026 14:14:41 +0900 Subject: [PATCH 5/7] feat: pacific-atlantic-water-flow solve --- pacific-atlantic-water-flow/haxr369.java | 127 +++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 pacific-atlantic-water-flow/haxr369.java diff --git a/pacific-atlantic-water-flow/haxr369.java b/pacific-atlantic-water-flow/haxr369.java new file mode 100644 index 0000000000..593086458e --- /dev/null +++ b/pacific-atlantic-water-flow/haxr369.java @@ -0,0 +1,127 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +class Solution { + + private final int[] dy = { -1, 1, 0, 0 }; + private final int[] dx = { 0, 0, -1, 1 }; + private int M = 0, N = 0; + + /** + * 특정 노드에서 시작에서 이웃 노드를 거쳐 두 바다로 갈 수 있는 노드 리스트를 출력하기 + * 특정 노드에서 전체 탐색? => O(NxM) x O(NxM) 탐색 필요. + * + * 그럼 태평양, 대서양 각각에서 도달할 수 있는 노드 리스트 찾기(본인 이상 값을 가진 노드로 탐색) + * 그리고 겹치는 지점 찾기 => 답 + * 3xO(NxM) + * + * Runtime: 11 ms (Beats 28.23%) + * Memory: 46.9 MB (Beats 98.39%) + * Space Complexity: O(NxM) + * - 노드 방문 여부를 체크하기 위한 flowed O(NxM) + * - 방문하는 노드를 큐에 찾기 qu O(NxM) + * > 2O(NxM) => O(NxM) + * Time Complexity: O(NxM) + * - 태평양 인접 노드 탐색 O(NxM) + * - 대서양 인접 노드 탐색 O(NxM) + * - 두 대양 인접 노드 검색 O(NxM) + * > 3O(NxM) + */ + public List> pacificAtlantic(int[][] heights) { + M = heights.length; + N = heights[0].length; + int[][] flowed = new int[M][N]; // 1이면 태평양 인접, 2면 대서양, 3이면 둘 다, 0이면 인접X + + // (0,0) ~ (0,N-1)을 1로 넣고 bfs 돌리기 + Queue qu = new LinkedList<>(); + for (int i = 0; i < N; i++) { + int[] temp = { 0, i }; + flowed[0][i] += 1; + qu.add(temp); + } + // (1, 0) ~ (M-1, 0) + for (int i = 1; i < M; i++) { + int[] temp = { i, 0 }; + flowed[i][0] += 1; + qu.add(temp); + } + // 태평양 탐색 + bfs(qu, flowed, heights, 1); + + // printMp(flowed); + + // System.out.println("------------"); + + qu = new LinkedList<>(); + // (M-1, 0) ~ (M-1, N-1) + for (int i = 0; i < N; i++) { + int[] temp = { M - 1, i }; + flowed[M - 1][i] += 2; + qu.add(temp); + } + // (0, 0) ~ (M-2, N-1) + for (int i = 0; i < M - 1; i++) { + int[] temp = { i, N - 1 }; + flowed[i][N - 1] += 2; + qu.add(temp); + } + // 태평양 탐색 + bfs(qu, flowed, heights, 2); + List> ans = new ArrayList<>(); + + for (int i = 0; i < M; i++) { + for (int j = 0; j < N; j++) { + if (flowed[i][j] == 3) { + List tmp = new ArrayList<>(Arrays.asList(i, j)); + ans.add(tmp); + } + } + } + + return ans; + + } + + private void bfs(Queue qu, int[][] flowed, int[][] heights, int oceanTp) { + while (!qu.isEmpty()) { + int[] node = qu.poll(); + int h = heights[node[0]][node[1]]; + + // 사방을 보면서 적절한 노드를 큐에 넣기 + for (int n = 0; n < 4; n++) { + int ny = node[0] + dy[n]; + int nx = node[1] + dx[n]; + + // 섬 밖 위치인지 체크 + if (ny < 0 || ny >= M || nx < 0 || nx >= N) { + continue; + } + // 방문했던 위치면 넘어가기 + if (flowed[ny][nx] >= oceanTp) { + continue; + } + // 바다에서 섬으로 갈 수 있는 방향인지 체크 + if (h > heights[ny][nx]) { + continue; + } + flowed[ny][nx] += oceanTp; + int[] temp = { ny, nx }; + qu.add(temp); + } + } + } + + private void printMp(int[][] mp) { + int my = mp.length; + int mx = mp[0].length; + for (int y = 0; y < my; y++) { + for (int x = 0; x < mx; x++) { + System.out.print(mp[y][x] + " "); + } + System.out.print('\n'); + } + } +} \ No newline at end of file From 1fdececee3222f423a72387a0b990de700c705c1 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Sat, 3 Jan 2026 14:14:58 +0900 Subject: [PATCH 6/7] feat: pacific-atlantic-water-flow solve --- pacific-atlantic-water-flow/haxr369.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pacific-atlantic-water-flow/haxr369.java b/pacific-atlantic-water-flow/haxr369.java index 593086458e..065ac728bf 100644 --- a/pacific-atlantic-water-flow/haxr369.java +++ b/pacific-atlantic-water-flow/haxr369.java @@ -124,4 +124,4 @@ private void printMp(int[][] mp) { System.out.print('\n'); } } -} \ No newline at end of file +} From 083dd827109f1e73dc8edb743e706349b5571bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=B0=AC=EC=86=94?= <53365713+haxr369@users.noreply.github.com> Date: Sat, 3 Jan 2026 21:47:32 +0900 Subject: [PATCH 7/7] Delete linked-list-cycle/Solution.java --- linked-list-cycle/Solution.java | 37 --------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 linked-list-cycle/Solution.java diff --git a/linked-list-cycle/Solution.java b/linked-list-cycle/Solution.java deleted file mode 100644 index 143b696bc9..0000000000 --- a/linked-list-cycle/Solution.java +++ /dev/null @@ -1,37 +0,0 @@ - -class ListNode { - int val; - ListNode next; - - ListNode(int x) { - val = x; - next = null; - } -} - -public class Solution { - - /** - * floyd 알고리즘(토끼 거북) 알고리즘 사용해서 - * 무한한 순환을 찾기 - */ - public boolean hasCycle(ListNode head) { - if (head == null) - return false; - - ListNode rb = head; - ListNode tt = head; - // 토끼와 거북이의 주소가 동일할 때까지 탐색하기 - while (rb.next != null && rb.next.next != null) { - // 토끼는 두 노드씩 이동하기 - rb = rb.next.next; - // 거북이는 한 노드씩 이동하기 - tt = tt.next; - if (rb == tt) { - // System.out.println("토끼("+rb.val+")와 거북이("+tt.val+")가 만났음"); - return true; - } - } - return false; - } -}