From e2f9d9f038e999124fdabd87cad3696c4916b57a Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Tue, 27 May 2025 09:54:43 +0900 Subject: [PATCH 1/9] add: linked-list-cycle --- linked-list-cycle/Solution.java | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 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 000000000..7f6221e66 --- /dev/null +++ b/linked-list-cycle/Solution.java @@ -0,0 +1,67 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Solution { + public boolean hasCycle(ListNode head) { + Set nSet = new HashSet<>(); + + while (head != null) { + if (nSet.contains(head)) { + return true; + } + + nSet.add(head); + head = head.next; + } + + return false; + } +} + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +// NOTE: 같은 val의 다른 Node의 경우를 고려하지 못했다 +class WrongSolution { + public boolean hasCycle(ListNode head) { + Map> vMap = new HashMap<>(); // NOTE: val, pos + + if (head == null) { + return false; + } + + ListNode cur = head; + boolean isCyclick = false; + int pos = -1; + while (cur != null) { + + if (vMap.containsKey(cur.val)) { + isCyclick = true; + break; + } + + List posList = new ArrayList<>(); + posList.add(pos++); + vMap.put(cur.val, posList); + cur = head.next; + } + + if (isCyclick) { + return true; + } else { + return false; + } + } +} \ No newline at end of file From aed3ca83097355c231d0de4ffbef0f5684de00cd Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Tue, 27 May 2025 09:55:13 +0900 Subject: [PATCH 2/9] add: [week-8] clong-graph --- clone-graph/Solution.java | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 clone-graph/Solution.java diff --git a/clone-graph/Solution.java b/clone-graph/Solution.java new file mode 100644 index 000000000..1d500f2fd --- /dev/null +++ b/clone-graph/Solution.java @@ -0,0 +1,86 @@ +import java.util.HashMap; +import java.util.Map; + +/* +// Definition for a Node. +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 Map nMap = new HashMap<>(); + + public Node cloneGraph(Node node) { + if (node == null) + return null; + + if (nMap.containsKey(node)) { + return nMap.get(node); + } + + Node clone = new Node(node.val); + nMap.put(node, clone); + + for (Node nei : node.neighbors) { + clone.neighbors.add(cloneGraph(nei)); + } + + return clone; + } +} + +class WrongSolution { + public Node graph; + public Map nMap = new HashMap<>(); + + public Node cloneGraph(Node node) { + if (node == null) + return null; + + graph = new Node(node.val); + nMap.put(node, graph); + + // print(graph); + + return clone(node, graph); + } + + public Node clone(Node node, Node cur) { + for (int i = 0; i < node.neighbors.size(); i++) { + Node adj = node.neighbors.get(i); + + if (nMap.containsKey(adj)) { + return nMap.get(adj); + } + + nMap.put(adj, new Node(adj.val)); + cur.neighbors.add(nMap.get(adj)); + clone(adj, nMap.get(adj)); + } + + return cur; + } + + public void print(Node node) { + System.out.println("visit " + node.val); + + for (int i = 0; i < node.neighbors.size(); i++) { + Node adj = node.neighbors.get(i); + System.out.println("nei " + adj.val); + print(adj); + } + } +} \ No newline at end of file From 1b3b88ef54aa0bf4a5e066d8b9220bce30d2589b Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Thu, 29 May 2025 08:23:17 +0900 Subject: [PATCH 3/9] add: Pacific Atlantic Water Flow --- .../{Solution.java => YoungSeok-Choi.java} | 2 +- .../{Solution.java => YoungSeok-Choi.java} | 2 +- .../YoungSeok-Choi.java | 113 ++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) rename clone-graph/{Solution.java => YoungSeok-Choi.java} (99%) rename linked-list-cycle/{Solution.java => YoungSeok-Choi.java} (99%) create mode 100644 pacific-atlantic-water-flow/YoungSeok-Choi.java diff --git a/clone-graph/Solution.java b/clone-graph/YoungSeok-Choi.java similarity index 99% rename from clone-graph/Solution.java rename to clone-graph/YoungSeok-Choi.java index 1d500f2fd..9c8b09ff8 100644 --- a/clone-graph/Solution.java +++ b/clone-graph/YoungSeok-Choi.java @@ -83,4 +83,4 @@ public void print(Node node) { print(adj); } } -} \ No newline at end of file +} diff --git a/linked-list-cycle/Solution.java b/linked-list-cycle/YoungSeok-Choi.java similarity index 99% rename from linked-list-cycle/Solution.java rename to linked-list-cycle/YoungSeok-Choi.java index 7f6221e66..28dafbfcf 100644 --- a/linked-list-cycle/Solution.java +++ b/linked-list-cycle/YoungSeok-Choi.java @@ -64,4 +64,4 @@ public boolean hasCycle(ListNode head) { return false; } } -} \ No newline at end of file +} diff --git a/pacific-atlantic-water-flow/YoungSeok-Choi.java b/pacific-atlantic-water-flow/YoungSeok-Choi.java new file mode 100644 index 000000000..a71981a67 --- /dev/null +++ b/pacific-atlantic-water-flow/YoungSeok-Choi.java @@ -0,0 +1,113 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// TC -> O(nm^2) 일 것으로 예상.. +class Solution { + + public boolean[][] visit; + public List> res = new ArrayList<>(); + public int w; + public int h; + + public int[] dx = { 0, 1, 0, -1 }; + public int[] dy = { 1, 0, -1, 0 }; + + public List> pacificAtlantic(int[][] heights) { + w = heights.length; + h = heights[0].length; + + if (w == h && w == 1) { + res.add(Arrays.asList(0, 0)); + return res; + } + + for (int i = 0; i < w; i++) { + for (int j = 0; j < h; j++) { + + boolean isTrue = false; + visit = new boolean[w][h]; + + isTrue |= dfsP(i, j, heights[i][j], heights); + + visit = new boolean[w][h]; + + isTrue &= dfsA(i, j, heights[i][j], heights); + + if (isTrue) { + res.add(Arrays.asList(i, j)); + } + } + } + + return res; + } + + public boolean dfsP(int x, int y, int prev, int[][] map) { + if (x < 0 || y < 0) { + return true; + } + + if (x >= w || y >= h) { + return false; + } + + if (visit[x][y]) { + return false; + } + + if (prev < map[x][y]) { + return false; + } + + visit[x][y] = true; + + boolean isTrue = false; + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + isTrue |= dfsP(nx, ny, map[x][y], map); + if (isTrue) { + return true; + } + } + + return isTrue; + } + + public boolean dfsA(int x, int y, int prev, int[][] map) { + if (x < 0 || y < 0) { + return false; + } + + if (x >= w || y >= h) { + return true; + } + + if (visit[x][y]) { + return false; + } + + if (prev < map[x][y]) { + return false; + } + + visit[x][y] = true; + + boolean isTrue = false; + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + isTrue |= dfsA(nx, ny, map[x][y], map); + + if (isTrue) { + return true; + } + + } + + return isTrue; + } +} From d0237c7e54b6fa39f049d77d4b2f541a401fc253 Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Thu, 29 May 2025 09:16:15 +0900 Subject: [PATCH 4/9] add: Sum of Two Integers --- sum-of-two-integers/YoungSeok-Choi.java | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 sum-of-two-integers/YoungSeok-Choi.java diff --git a/sum-of-two-integers/YoungSeok-Choi.java b/sum-of-two-integers/YoungSeok-Choi.java new file mode 100644 index 000000000..adffc96be --- /dev/null +++ b/sum-of-two-integers/YoungSeok-Choi.java @@ -0,0 +1,32 @@ + +// tc -> O(1) +// NOTE: 자바의 Integer.parseInt는 음수 표현을 처리하지 못함.. 양의 부호가 없는 이진수만 지원. (음수의 경우 1111111~ 로 시작하는 이진 문자열을 양수로 해석하려 시도해 런타임 오류 발생) +class Solution { + public int getSum(int a, int b) { + String aStr = String.format("%32s", Integer.toBinaryString(a)).replace(" ", "0"); + String bStr = String.format("%32s", Integer.toBinaryString(b)).replace(" ", "0"); + char[] sum = new char[32]; + boolean isCarry = false; + + for (int i = sum.length - 1; i >= 0; i--) { + if (aStr.charAt(i) == bStr.charAt(i) && aStr.charAt(i) == '1') { + + sum[i] = isCarry ? '1' : '0'; + isCarry = true; + continue; + } + + if (aStr.charAt(i) == '1' || bStr.charAt(i) == '1') { + sum[i] = isCarry ? '0' : '1'; + isCarry = isCarry ? true : false; + continue; + } + + sum[i] = isCarry ? '1' : '0'; + isCarry = false; + } + + String resStr = new String(sum); + return (int) Long.parseLong(resStr, 2); + } +} From b071d3ea09a9a2a2f6b40d37160e0aa24e9b34c4 Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Fri, 30 May 2025 00:25:47 +0900 Subject: [PATCH 5/9] add: maximon product subarry --- maximum-product-subarray/YoungSeok.java | 100 ++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 maximum-product-subarray/YoungSeok.java diff --git a/maximum-product-subarray/YoungSeok.java b/maximum-product-subarray/YoungSeok.java new file mode 100644 index 000000000..6f3019c05 --- /dev/null +++ b/maximum-product-subarray/YoungSeok.java @@ -0,0 +1,100 @@ +import java.util.ArrayList; +import java.util.List; + +// 답지보고 풀이.. +class Solution { + public int maxProduct(int[] nums) { + int max = nums[0]; + int currMax = nums[0]; + int currMin = nums[0]; + + for (int i = 1; i < nums.length; i++) { + int temp = currMax; + currMax = Math.max(nums[i], Math.max(currMax * nums[i], currMin * nums[i])); + currMin = Math.min(nums[i], Math.min(temp * nums[i], currMin * nums[i])); + max = Math.max(max, currMax); + } + + return max; + } +} + +// NOTE:핵심 컨셉은 0을 만나기 전까지 한칸씩 늘려가며 모든 원소의 곱을 만든다. 0을 만나면 첫 번째 원소를 뺀 나머지 원소들의 곱의 +// 값으로 최대값을 계속 갱신해나간다. +class WrongSolution { + + public int mx = -98764321; + public List bList = new ArrayList<>(); + public boolean isStartInit = true; + public boolean isOverZero = false; + + public int maxProduct(int[] nums) { + int start = 1; + int zeroIdx = 0; + if (nums.length == 1) { + return nums[0]; + } + + for (int i = 0; i < nums.length; i++) { + + if (nums[i] == 0) { + if (mx <= 0) { + bList.add(false); + } else { + bList.add(true); + } + + while (zeroIdx < i) { + start /= nums[zeroIdx]; + mx = Math.max(mx, start); + + if (mx >= 1) { + bList.add(true); + } + + zeroIdx++; + } + + start = 1; + isStartInit = true; + zeroIdx++; // 0값인 인덱스를 건너뛰고 다음 번 인덱스를 대입 + } else { + start *= nums[i]; + mx = Math.max(mx, start); + + if (start >= 1) { + isStartInit = false; + isOverZero = true; + } + } + } + + while (zeroIdx < nums.length) { + start /= nums[zeroIdx]; + mx = Math.max(mx, start); + zeroIdx++; + } + + mx = Math.max(mx, nums[nums.length - 1]); + + if (nums[nums.length - 1] >= 1) { + isOverZero = true; + } + + if (mx > 0 && isOverZero) { + bList.add(true); + } + + for (boolean b : bList) { + if (b) { + return mx; + } + } + + if (bList.size() > 0) { + return isStartInit ? 0 : mx; + } + + return mx; + } +} \ No newline at end of file From 110d2e3b8998d06db13ae500cf4d8bf1506e9618 Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Fri, 30 May 2025 00:26:14 +0900 Subject: [PATCH 6/9] fix: lint --- maximum-product-subarray/YoungSeok.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maximum-product-subarray/YoungSeok.java b/maximum-product-subarray/YoungSeok.java index 6f3019c05..e2f1a9356 100644 --- a/maximum-product-subarray/YoungSeok.java +++ b/maximum-product-subarray/YoungSeok.java @@ -97,4 +97,4 @@ public int maxProduct(int[] nums) { return mx; } -} \ No newline at end of file +} From 7d72d8019cc65b69667a713fd1041f5fba552d5e Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Fri, 30 May 2025 22:12:09 +0900 Subject: [PATCH 7/9] add: Palindrimic substrings --- palindromic-substrings/YoungSeok-Choi.java | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 palindromic-substrings/YoungSeok-Choi.java diff --git a/palindromic-substrings/YoungSeok-Choi.java b/palindromic-substrings/YoungSeok-Choi.java new file mode 100644 index 000000000..d38367fd1 --- /dev/null +++ b/palindromic-substrings/YoungSeok-Choi.java @@ -0,0 +1,43 @@ +// tc O(n^3)... 입력값이 조금만 켜졌으면 바로 TLE가 발생했을 것.. +class Solution { + public int countSubstrings(String s) { + int pCnt = 0; + + for (int i = 1; i <= s.length(); i++) { + String window = s.substring(0, i); + String prev = window; + + if (isPalindrome(window)) + pCnt++; + + for (int j = window.length(); j < s.length(); j++) { + prev = new StringBuilder(prev).append(s.charAt(j)).substring(1); + if (isPalindrome(prev)) { + pCnt++; + } + } + } + + return pCnt; + } + + public boolean isPalindrome(String p) { + + if (p.length() <= 0) + return false; + + int start = 0; + int end = p.length() - 1; + + while (start <= end) { + if (p.charAt(start) != p.charAt(end)) { + return false; + } + + start++; + end--; + } + + return true; + } +} From 678bb7d383099f489a281bf33bb918bb9893233e Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Sat, 31 May 2025 10:22:49 +0900 Subject: [PATCH 8/9] add: lcs, max product subArray --- .../YoungSeok-Choi.java | 86 +++++++++++++++++++ .../{YoungSeok.java => YoungSeok-Choi.java} | 2 + 2 files changed, 88 insertions(+) create mode 100644 longest-common-subsequence/YoungSeok-Choi.java rename maximum-product-subarray/{YoungSeok.java => YoungSeok-Choi.java} (94%) diff --git a/longest-common-subsequence/YoungSeok-Choi.java b/longest-common-subsequence/YoungSeok-Choi.java new file mode 100644 index 000000000..add8805a9 --- /dev/null +++ b/longest-common-subsequence/YoungSeok-Choi.java @@ -0,0 +1,86 @@ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class Solution { + private Map memo = new HashMap<>(); + + public int longestCommonSubsequence(String t1, String t2) { + return lcs(0, 0, t1, t2); + } + + private int lcs(int i, int j, String t1, String t2) { + if (i == t1.length() || j == t2.length()) { + return 0; + } + + String key = i + "," + j; + if (memo.containsKey(key)) { + return memo.get(key); + } + + int res; + if (t1.charAt(i) == t2.charAt(j)) { + res = 1 + lcs(i + 1, j + 1, t1, t2); + } else { + res = Math.max(lcs(i + 1, j, t1, t2), lcs(i, j + 1, t1, t2)); + } + + memo.put(key, res); + return res; + } +} + +class WrongSolution { + public int longestCommonSubsequence(String t1, String t2) { + Map> sMap = new HashMap<>(); + int cnt = 0; + + // t1의 연속으로 등장하는 문자열을 하나로만 바꾸기 (e.g. abbbvvvvssssmmmddd -> abvsmd) + StringBuilder sb = new StringBuilder(); + char start = t1.charAt(0); + sb.append(start); + for (int i = 1; i < t1.length(); i++) { + if (start != t1.charAt(i)) { + sb.append(t1.charAt(i)); + start = t1.charAt(i); + } + } + + t1 = sb.toString(); + + for (int i = 0; i < t1.length(); i++) { + sMap.computeIfAbsent(t1.charAt(i) - 97, k -> new ArrayList<>()).add(i); + } + + StringBuilder filtered = new StringBuilder(); + for (int i = 0; i < t2.length(); i++) { + int alpIdx = t2.charAt(i) - 97; + if (sMap.containsKey(alpIdx)) { + filtered.append(t2.charAt(i)); + } + } + t2 = filtered.toString(); + + int prevT1Idx = -1; + for (int i = 0; i < t2.length(); i++) { + int alpIdx = t2.charAt(i) - 97; + + List idxList = sMap.get(alpIdx); + if (idxList == null) + continue; + + for (int idx : idxList) { + if (idx > prevT1Idx) { + cnt++; + prevT1Idx = idx; + break; + } + } + } + + return cnt; + } +} diff --git a/maximum-product-subarray/YoungSeok.java b/maximum-product-subarray/YoungSeok-Choi.java similarity index 94% rename from maximum-product-subarray/YoungSeok.java rename to maximum-product-subarray/YoungSeok-Choi.java index e2f1a9356..1615785f2 100644 --- a/maximum-product-subarray/YoungSeok.java +++ b/maximum-product-subarray/YoungSeok-Choi.java @@ -21,6 +21,8 @@ public int maxProduct(int[] nums) { // NOTE:핵심 컨셉은 0을 만나기 전까지 한칸씩 늘려가며 모든 원소의 곱을 만든다. 0을 만나면 첫 번째 원소를 뺀 나머지 원소들의 곱의 // 값으로 최대값을 계속 갱신해나간다. + +// 위의 아이디어로 문제를 풀이했지만, 모든 경우의 예외를 핸들링 할 수가 없어 풀이를 더이상 진행하지 않았다.. class WrongSolution { public int mx = -98764321; From e6dd7cdfd636828db80ed2ff3994c771e046578d Mon Sep 17 00:00:00 2001 From: "Yongseok.choi" Date: Sat, 31 May 2025 18:34:17 +0900 Subject: [PATCH 9/9] add: min-window-substr --- minimum-window-substring/YoungSeok-Choi.java | 104 +++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 minimum-window-substring/YoungSeok-Choi.java diff --git a/minimum-window-substring/YoungSeok-Choi.java b/minimum-window-substring/YoungSeok-Choi.java new file mode 100644 index 000000000..1d1db707d --- /dev/null +++ b/minimum-window-substring/YoungSeok-Choi.java @@ -0,0 +1,104 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class Solution { + public String minWindow(String s, String t) { + if (s.length() < t.length()) { + return ""; + } + + Map charCount = new HashMap<>(); + for (char ch : t.toCharArray()) { + charCount.put(ch, charCount.getOrDefault(ch, 0) + 1); + } + + int targetCharsRemaining = t.length(); + int[] minWindow = { 0, Integer.MAX_VALUE }; + int startIndex = 0; + + for (int endIndex = 0; endIndex < s.length(); endIndex++) { + char ch = s.charAt(endIndex); + if (charCount.containsKey(ch) && charCount.get(ch) > 0) { + targetCharsRemaining--; + } + charCount.put(ch, charCount.getOrDefault(ch, 0) - 1); + + if (targetCharsRemaining == 0) { + while (true) { + char charAtStart = s.charAt(startIndex); + if (charCount.containsKey(charAtStart) && charCount.get(charAtStart) == 0) { + break; + } + charCount.put(charAtStart, charCount.getOrDefault(charAtStart, 0) + 1); + startIndex++; + } + + if (endIndex - startIndex < minWindow[1] - minWindow[0]) { + minWindow[0] = startIndex; + minWindow[1] = endIndex; + } + + charCount.put(s.charAt(startIndex), charCount.getOrDefault(s.charAt(startIndex), 0) + 1); + targetCharsRemaining++; + startIndex++; + } + } + + return minWindow[1] >= s.length() ? "" : s.substring(minWindow[0], minWindow[1] + 1); + } +} + +class WrongSolution { // 알고리즘은 맞지만 시간초과 발생... O(n)의 sliding window 방식으로 풀어야 했던 문제.. + public String minWindow(String s, String t) { + Map targetMap = new HashMap<>(); + List candidates = new ArrayList<>(); + for (char c : t.toCharArray()) { + targetMap.put(c, targetMap.getOrDefault(c, 0) + 1); + } + + String minStr = null; + for (int i = 0; i < s.length(); i++) { + if (targetMap.containsKey(s.charAt(i))) { + candidates.add(i); + } + } + + int size = candidates.size(); + + while (size > 0) { + Map windowMap = new HashMap<>(targetMap); + int targetCnt = t.length(); + int startIdx = candidates.remove(0); + int endIdx = -999; + + for (int i = startIdx; i < s.length(); i++) { + char at = s.charAt(i); + + if (windowMap.containsKey(at) && windowMap.get(at) > 0) { + windowMap.put(at, windowMap.get(at) - 1); + targetCnt--; + } + + if (targetCnt == 0) { + endIdx = i + 1; + break; + } + } + + if (targetCnt == 0) { + if (minStr == null) { + minStr = s.substring(startIdx, endIdx); + } else { + int prevSize = minStr.length(); + minStr = prevSize < Math.abs(endIdx - startIdx) ? minStr : s.substring(startIdx, endIdx); + } + } + + size--; + } + + return minStr == null ? "" : minStr; + } +}