From 668e45f4b4e7feddc9d49d64477cfe3d15054cdd Mon Sep 17 00:00:00 2001 From: JIA Date: Sat, 30 Aug 2025 01:12:15 +0900 Subject: [PATCH 1/2] - weeks 06 --- .../Geegong.java | 94 +++++++++++++++++++ .../Geegong.java | 35 +++++++ longest-increasing-subsequence/Geegong.java | 63 +++++++++++++ spiral-matrix/Geegong.java | 79 ++++++++++++++++ 4 files changed, 271 insertions(+) create mode 100644 design-add-and-search-words-data-structure/Geegong.java create mode 100644 find-minimum-in-rotated-sorted-array/Geegong.java create mode 100644 longest-increasing-subsequence/Geegong.java create mode 100644 spiral-matrix/Geegong.java diff --git a/design-add-and-search-words-data-structure/Geegong.java b/design-add-and-search-words-data-structure/Geegong.java new file mode 100644 index 000000000..08dfc87e2 --- /dev/null +++ b/design-add-and-search-words-data-structure/Geegong.java @@ -0,0 +1,94 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Geegong { + + /** + * case 1. Letter 라는 클래스 안에 각 char 를 가지고 있고 하나씩 순회하면서 search 를 하니 응답속도가 너무 느림.. + */ + class WordDictionary { + public Map> wordsLengthMap; + + public WordDictionary() { + this.wordsLengthMap = new HashMap<>(); + } + + public void addWord(String word) { + char[] wordChars = word.toCharArray(); + + Letter prev = new Letter(null); + Letter root = new Letter(prev); + for (char wordChar : wordChars) { + Letter curr = new Letter(wordChar, false); + + prev.nextLetter = curr; + + prev = curr; + } + + prev.isEnd = true; + + wordsLengthMap.computeIfAbsent(wordChars.length, ArrayList::new).add(root.nextLetter); + } + + public boolean search(String word) { + char[] wordChars = word.toCharArray(); + int length = wordChars.length; + + if (!wordsLengthMap.containsKey(length)) { + return false; + } + + List letters = wordsLengthMap.get(length); + for (Letter letter : letters) { + if (letter.isMatched(wordChars)) { + return true; + } + } + + return false; + } + } + + public static class Letter { + public char currentLetterOfAsciiCode; // '?'-'a' + public Letter nextLetter; + public boolean isEnd; // 마지막 글자 인지 여부 + + public Letter(Letter next) { + this.nextLetter = next; + } + + public Letter(char wordChar, boolean isEnd) { + this.currentLetterOfAsciiCode = wordChar; + this.isEnd = isEnd; + } + + public boolean isMatched(char[] wordChars) { + + Letter current = this.nextLetter; + // 본인 시점으로 부터 wordChars 마지막까지 체크 + for (char wordChar : wordChars) { + + // . 이면 그냥 패스 + boolean isMatched = wordChar == '.' || wordChar == current.currentLetterOfAsciiCode; + if (isMatched) { + if (current.isEnd) { + return true; + } else { + current = current.nextLetter; + } + + } else { + return false; + } + } + + return false; + + } + } +} + diff --git a/find-minimum-in-rotated-sorted-array/Geegong.java b/find-minimum-in-rotated-sorted-array/Geegong.java new file mode 100644 index 000000000..ca6c1bf1d --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/Geegong.java @@ -0,0 +1,35 @@ +public class Geegong { + + /** + * two pointer 사용 + * time complexity : o(log n) + * space complexity : o(1) + * + * when nums are sorted array, binary search could be used in O(log n) + * (rotating doesn't matter) + * @param nums + * @return + */ + public int findMin(int[] nums) { + int leftIndex = 0; + int rightIndex = nums.length - 1; + + while(leftIndex < rightIndex) { + int midIndex = leftIndex + ((rightIndex - leftIndex) / 2); + + if (nums[midIndex] > nums[rightIndex]) { + leftIndex = midIndex + 1; + // midIndex 에 +1 하는 이유는 midIndex 값은 이미 rightIndex 보다 크다고 판단이 되기에 최솟값이 될 수 없어 + // midIndex 의 값은 배제한다. + } else if (nums[midIndex] < nums[rightIndex]) { + rightIndex = midIndex - 1; + } else if (nums[midIndex] == nums[rightIndex]) { // 두개 인덱스가 같아질 수가 있나? + return nums[midIndex]; + } + } + + return nums[leftIndex]; + } + +} + diff --git a/longest-increasing-subsequence/Geegong.java b/longest-increasing-subsequence/Geegong.java new file mode 100644 index 000000000..c14118a2a --- /dev/null +++ b/longest-increasing-subsequence/Geegong.java @@ -0,0 +1,63 @@ +import java.util.Arrays; + +public class Geegong { + + /** + * case 1. binarySearch 를 이용, 범위를 1개의 원소부터 시작해서 점차 늘릴 수 있는 LIS 를 별도 변수에서 관리 + * 그리고 정렬이 되어가는 배열을 따로 저장하는 배열도 필요 + * Patience Sorting 아이디어 (?) -> 찾아보자 + * time complexity : + * O(log n) - binary search 이고 + * 위 bs 를 각 원소별로 진행하기 때문에 o(n log n) + * space complexity : O(n) + * + * case 2. DP + * dp[i] => nums 의 i 번째 인덱스까지의 LIS 최장 길이를 의미 + * time complexity : O(n^2) + * space complexity : O(n) + * + * @param nums + * @return + */ +// public static int lengthOfLIS(int[] nums) { +// int n = nums.length; +// int[] tails = new int[n]; +// int size = 0; +// +// for (int x : nums) { +// // 0 ~ size 안에서 이분탐색으로 넣을 수 있는 자리가 있으면 그 자리의 index 리턴 (따라서 tc 는 o(n log n) +// // 넣을 수 없으면 음수값을 리턴하는데 ret = - (insertionPosition - 1) +// // (0~size) 안에서 x 가 들어갈 수 있는 index는?=> insertionPosition = - (ret + 1) 이렇게 획득 +// int i = Arrays.binarySearch(tails, 0, size, x); +// if (i < 0) i = -(i + 1); // lower_bound +// tails[i] = x; +// // size 는 nums 안에 원소들을 하나씩 훑어가면서 지금까지 LIS의 최장 길이 +// if (i == size) size++; +// } +// return size; +// } + + public static int lengthOfLIS(int[] nums) { + int[] dp = new int[nums.length + 1]; + int maxLIS = 0; + + for (int index=0; index 맨 처음에는 이렇게 생각했으나 + dp[index] = Math.max(dp[index], dp[innerIndex] + 1); + // dp[innerIndex] + 1 에서 +1을 한 이유는 innerIndex의 값과 index의 값까지가 LIS가 될 것이기 때문에 더해진 것 + } + } + + maxLIS = Math.max(maxLIS, dp[index]); + } + + return maxLIS; + } + + +} + diff --git a/spiral-matrix/Geegong.java b/spiral-matrix/Geegong.java new file mode 100644 index 000000000..0651f039a --- /dev/null +++ b/spiral-matrix/Geegong.java @@ -0,0 +1,79 @@ +import java.util.ArrayList; +import java.util.List; + +public class Geegong { + + /** + * direction vector 와 vistited 배열을 이용해 메모이제이션을 활용하여 풀어보기 + * time complexity : o(n) + * space complexity : o(n) - result 용 + * @param matrix + * @return + */ + // move Colum direction , move Row Direction + public int[][] directionVectors = {{0,1}, {1,0}, {0,-1}, {-1, 0}}; + public List spiralOrder(int[][] matrix) { + + List result = new ArrayList<>(matrix.length * matrix[0].length); + + // for memoization, 방문한 matrix의 인덱스들을 저장 + // int 배열은 기본으로 0 이 초기화 + int[][] visited = new int[matrix.length][matrix[0].length]; + + makeSpiralMatrix(matrix, 0,0, 0, result, visited); + + return result; + } + + public void makeSpiralMatrix(int[][] matrix, int startRowIdx, int startColIdx, int directionOrder, List result, int[][] visited) { + if (startRowIdx < 0 || startRowIdx >= matrix.length || startColIdx < 0 || startColIdx >= matrix[0].length) { + return; + } + + // 방문했던 녀석을 다시 찾아온거라면 다 돌았다고 판단하고 recursive 종료 + if (visited[startRowIdx][startColIdx] == 1) { + return; + } + + // 이번 순서의 vector 를 가져온다 + int[] direction = directionVectors[directionOrder]; + + // row, col 각각 어떤 방향으로 움직일지 지정 + int moveRowPos = direction[0]; + int moveColPos = direction[1]; + + int count = 0; + + int rowIndex = startRowIdx + (moveRowPos * count); + int colIndex = startColIdx + (moveColPos * count); + + do { + int currentVal = matrix[rowIndex][colIndex]; + result.add(currentVal); + visited[rowIndex][colIndex] = 1; + + count++; + rowIndex = startRowIdx + (moveRowPos * count); + colIndex = startColIdx + (moveColPos * count); + if (colIndex < 0 || colIndex >= matrix[0].length || rowIndex < 0 || rowIndex >= matrix.length) { + break; + } + + } while(visited[rowIndex][colIndex] != 1); + + // vector 리스트들은 0번째, 1번째, 2번째, 3번째, 0번째, 1번째 .. 이 순서대로 꺼내서 사용한다 + int nextDirectionOrder = directionOrder + 1 >= directionVectors.length ? 0 : directionOrder + 1; + // 다음 방향을 미리 지정 + int[] nextDirection = directionVectors[nextDirectionOrder]; + + // 다음 방향의 시작점 미리 지정 + count--; + int nextStartRowIdx = startRowIdx + (moveRowPos * count) + nextDirection[0]; + int nextStartColIdx = startColIdx + (moveColPos * count) + nextDirection[1]; + + makeSpiralMatrix(matrix, nextStartRowIdx, nextStartColIdx, nextDirectionOrder, result, visited); + } +} + + + From 4a8520827e5bca6b99fa2d78727b7f0bf52c66a9 Mon Sep 17 00:00:00 2001 From: JIA Date: Sat, 30 Aug 2025 16:32:34 +0900 Subject: [PATCH 2/2] =?UTF-8?q?-=20valid=20parentheses=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-parentheses/Geegong.java | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 valid-parentheses/Geegong.java diff --git a/valid-parentheses/Geegong.java b/valid-parentheses/Geegong.java new file mode 100644 index 000000000..867a62581 --- /dev/null +++ b/valid-parentheses/Geegong.java @@ -0,0 +1,38 @@ +import java.util.HashMap; +import java.util.Stack; + +public class Geegong { + + /** + * stack 자료구조 사용 + * 닫는 부분만 hashMap의 key 값으로 서로 페어가 되는 값을 value 로 한다. + * stack 자료구조는 닫는 bracket이 아니면 push 해서 넣고 닫는 bracket 만 체크를 하는데 + * stack 에서 pop 을 하는데 이떄 map의 value와 다르면 false + * + * time complexity : o(n) + * space complexity : o(1) + * @param s + * @return + */ + public boolean isValid(String s) { + HashMap map = new HashMap(); + map.put(')', '('); + map.put(']', '['); + map.put('}', '{'); + + Stack stack = new Stack(); + for (int i=0; i