diff --git a/alien-dictionary/imsosleepy.java b/alien-dictionary/imsosleepy.java new file mode 100644 index 000000000..f71eca385 --- /dev/null +++ b/alien-dictionary/imsosleepy.java @@ -0,0 +1,65 @@ +// 처음 봤을 때는 단순 노가다라 생각했는데, prefix 문제가 너무 까다로웠음 +// 사이클 탐지도 마지막에 두면 더 편했는데 코드가 너무 길어지는거 같아서 GPT의 도움을 받았다. +// 다 정리하고 ㅂ니 코드 자체는 어렵지 않았음. +// 코치 여러분, 그리고 스터디 참여한 모두 수고하셨습니다. +public class AlienDictionary { + public String alienOrder(String[] words) { + Map> graph = new HashMap<>(); + Map inDegree = new HashMap<>(); + + for (String word : words) { + for (char c : word.toCharArray()) { + graph.putIfAbsent(c, new HashSet<>()); + inDegree.putIfAbsent(c, 0); + } + } + + for (int i = 0; i < words.length - 1; i++) { + String first = words[i]; + String second = words[i + 1]; + + // invalid case: prefix 문제 + if (first.length() > second.length() && first.startsWith(second)) { + return ""; + } + + for (int j = 0; j < Math.min(first.length(), second.length()); j++) { + char c1 = first.charAt(j); + char c2 = second.charAt(j); + if (c1 != c2) { + if (!graph.get(c1).contains(c2)) { + graph.get(c1).add(c2); + inDegree.put(c2, inDegree.get(c2) + 1); + } + break; + } + } + } + + PriorityQueue pq = new PriorityQueue<>(); + for (char c : inDegree.keySet()) { + if (inDegree.get(c) == 0) { + pq.offer(c); + } + } + + StringBuilder result = new StringBuilder(); + while (!pq.isEmpty()) { + char current = pq.poll(); + result.append(current); + for (char neighbor : graph.get(current)) { + inDegree.put(neighbor, inDegree.get(neighbor) - 1); + if (inDegree.get(neighbor) == 0) { + pq.offer(neighbor); + } + } + } + + // invalid case: 사이클 문제 + if (result.length() != inDegree.size()) { + return ""; + } + + return result.toString(); + } +} diff --git a/longest-palindromic-substring/imsosleepy.java b/longest-palindromic-substring/imsosleepy.java new file mode 100644 index 000000000..faf919fdf --- /dev/null +++ b/longest-palindromic-substring/imsosleepy.java @@ -0,0 +1,71 @@ +// 투포인터와 유사한 방식의 풀이가 하나 더 있었음 +// 다만 모든 문자열이 가운데가 될 수 있다는 조건이 너무 까다로워서 구현에는 실패함 +// DP와 같은 O(N^2)이 되지만 공간사용량이 압도적으로 적어서 시간차이가 많이 나게 됨 +// GPT의 도움을 받았음 +class Solution { + public String longestPalindrome(String s) { + if (s == null || s.length() < 1) return ""; + + int start = 0, end = 0; + + for (int i = 0; i < s.length(); i++) { + int len1 = expandAroundCenter(s, i, i); + int len2 = expandAroundCenter(s, i, i + 1); + int len = Math.max(len1, len2); + + + if (len > end - start) { + start = i - (len - 1) / 2; + end = i + len / 2; + } + } + + return s.substring(start, end + 1); + } + + private int expandAroundCenter(String s, int left, int right) { + while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { + left--; + right++; + } + return right - left - 1; + } +} + +// 가장 먼저 생각한 풀이. 회문하면 떠오르는게 DP인데 이런 방식을 바라는게 아닌거같음 +class Solution { + public String longestPalindrome(String s) { + int n = s.length(); + boolean[][] dp = new boolean[n][n]; + + int start = 0, maxLen = 1; + + // 길이가 1인 경우 + for (int i = 0; i < n; i++) { + dp[i][i] = true; + } + + // 길이가 2인 경우 + for (int i = 0; i < n - 1; i++) { + if (s.charAt(i) == s.charAt(i + 1)) { + dp[i][i + 1] = true; + start = i; + maxLen = 2; + } + } + + for (int len = 3; len <= n; len++) { + for (int i = 0; i <= n - len; i++) { + int j = i + len - 1; + + if (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]) { + dp[i][j] = true; + start = i; + maxLen = len; + } + } + } + + return s.substring(start, start + maxLen); + } +} diff --git a/rotate-image/imsosleepy.java b/rotate-image/imsosleepy.java new file mode 100644 index 000000000..ec7f502af --- /dev/null +++ b/rotate-image/imsosleepy.java @@ -0,0 +1,24 @@ +// You have to rotate the image in-place 라는말을 별 생각 안하고 풀다가 오래걸림 +// "matrix내"에서 문제의 요구사항 대로 회전시켜줘야 한다. 유지해야한다 +// matrix[i][j]를 matrix[j][i]로 바꾸고 각 행을 좌우로 뒤집는다. +class Solution { + public void rotate(int[][] matrix) { + int n = matrix.length; + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + int temp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = temp; + } + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n / 2; j++) { + int temp = matrix[i][j]; + matrix[i][j] = matrix[i][n - 1 - j]; + matrix[i][n - 1 - j] = temp; + } + } + } +} diff --git a/subtree-of-another-tree/imsosleepy.java b/subtree-of-another-tree/imsosleepy.java new file mode 100644 index 000000000..8c9f9d749 --- /dev/null +++ b/subtree-of-another-tree/imsosleepy.java @@ -0,0 +1,20 @@ +// 이지문제가 아닌거 같다. 루트 노드를 반복 검증해야하는데 방법을 못 찾아서 오래걸림 +// 시간 복잡도는 O(root의 길이*subRoot의 길이) +class Solution { + public boolean isSubtree(TreeNode root, TreeNode subRoot) { + if (root == null) return false; + + if (isSameTree(root, subRoot)) return true; + + return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + } + + private boolean isSameTree(TreeNode a, TreeNode b) { + if (a == null && b == null) return true; // 둘 다 null이면 같음 + if (a == null || b == null) return false; // 하나만 null이면 다름 + if (a.val != b.val) return false; // 값이 다르면 다름 + + // DFS로 지속 검증 + return isSameTree(a.left, b.left) && isSameTree(a.right, b.right); + } +} diff --git a/validate-binary-search-tree/imsosleepy.java b/validate-binary-search-tree/imsosleepy.java new file mode 100644 index 000000000..5290f91f0 --- /dev/null +++ b/validate-binary-search-tree/imsosleepy.java @@ -0,0 +1,17 @@ +// 이진 탐색트리는 보통 O(N) ~ O(NlogN)을 요구한다. +// 그래서 이번에도 모든 노드를 한번만 탐색하는게 목표 +// Node.val의 숫자 크기 때문에 Max_VALUE를 잘 지정해주면 바로 풀림 +class Solution { + public boolean isValidBST(TreeNode root) { + return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + private boolean isValidBST(TreeNode node, long min, long max) { + if (node == null) return true; + + if (node.val <= min || node.val >= max) return false; + + return isValidBST(node.left, min, node.val) && + isValidBST(node.right, node.val, max); + } +}