From 3f815c0825cd73b439beb8d1c933e0db85d7ee2d Mon Sep 17 00:00:00 2001 From: devtkwon Date: Tue, 20 Aug 2024 22:55:25 +0900 Subject: [PATCH 1/6] valid-anagram --- valid-anagram/taekwon-dev.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 valid-anagram/taekwon-dev.java diff --git a/valid-anagram/taekwon-dev.java b/valid-anagram/taekwon-dev.java new file mode 100644 index 000000000..7ffee7555 --- /dev/null +++ b/valid-anagram/taekwon-dev.java @@ -0,0 +1,11 @@ +class Solution { + public boolean isAnagram(String s, String t) { + char[] sChars = s.toCharArray(); + char[] tChars = t.toCharArray(); + + Arrays.sort(sChars); + Arrays.sort(tChars); + + return Arrays.equals(sChars, tChars); + } +} From 800725bd9f3617fcac70779fa183940aee1fa56b Mon Sep 17 00:00:00 2001 From: devtkwon Date: Tue, 20 Aug 2024 23:09:12 +0900 Subject: [PATCH 2/6] docs: Add explanation of time and space complexity --- valid-anagram/taekwon-dev.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/valid-anagram/taekwon-dev.java b/valid-anagram/taekwon-dev.java index 7ffee7555..60221ffa5 100644 --- a/valid-anagram/taekwon-dev.java +++ b/valid-anagram/taekwon-dev.java @@ -1,3 +1,10 @@ +/** + * 시간 복잡도: O(NlogN) + * - Arrays.sort() > Dual-Pivot QuickSort + * + * 공간 복잡도: O(N) + * + */ class Solution { public boolean isAnagram(String s, String t) { char[] sChars = s.toCharArray(); From d75317cf02196d64be0f9c70302cb5fa8b4e060e Mon Sep 17 00:00:00 2001 From: devtkwon Date: Tue, 20 Aug 2024 23:21:57 +0900 Subject: [PATCH 3/6] fix: valid-anagram --- valid-anagram/taekwon-dev.java | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/valid-anagram/taekwon-dev.java b/valid-anagram/taekwon-dev.java index 60221ffa5..c93377b32 100644 --- a/valid-anagram/taekwon-dev.java +++ b/valid-anagram/taekwon-dev.java @@ -4,15 +4,28 @@ * * 공간 복잡도: O(N) * + * 처음 문제를 보고 들었던 생각: 정렬 시켜서 같으면 anagram? + * -> 아, 그러면 등장한 문자의 빈도수가 같네? + * -> 결국 26 사이즈가 인풋에 영향을 받지 않으므로 공간 복잡도를 O(1)로 개선할 수 있고, + * -> 시간 복잡도도 O(N)으로 개선할 수 있겠다. */ class Solution { public boolean isAnagram(String s, String t) { - char[] sChars = s.toCharArray(); - char[] tChars = t.toCharArray(); + if (s.length() != t.length()) return false; - Arrays.sort(sChars); - Arrays.sort(tChars); + int[] charCount = new int[26]; - return Arrays.equals(sChars, tChars); + for (char c : s.toCharArray()) { + charCount[c - 'a']++; + } + + for (char c : t.toCharArray()) { + charCount[c - 'a']--; + if (charCount[c - 'a'] < 0) { + return false; + } + } + + return true; } } From 95d5f23105987ea938e65c1f12ddbc72675436b3 Mon Sep 17 00:00:00 2001 From: devtkwon Date: Sat, 24 Aug 2024 09:16:34 +0900 Subject: [PATCH 4/6] counting-bits --- counting-bits/taekwon-dev.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 counting-bits/taekwon-dev.java diff --git a/counting-bits/taekwon-dev.java b/counting-bits/taekwon-dev.java new file mode 100644 index 000000000..941efe18a --- /dev/null +++ b/counting-bits/taekwon-dev.java @@ -0,0 +1,19 @@ +/** + * 공간 복잡도: O(N) + * 시간 복잡도: O(N) + * - 만약 1 ~ N 까지 각 수에 대해서 이진수로 변환한 뒤 1의 개수를 카운트 했다면? - O(NlogN) + * Note: + * - a >> b: a 의 이진 표현을 오픈쪽으로 b 비트만큼 이동 + * - i >> 1: a 의 이진 표현에서 가장 오픈쪽 하나가 잘림 (i는 양수 범위를 가지므로, 왼쪽은 0으로 채워짐) + * - a & b: AND 연산 + * - i & 1: 이전 결과 값이 메모되어 있으므로, 내가 궁금한 것 가장 마지막 자리 수 값이 1인지 여부. + */ +class Solution { + public int[] countBits(int n) { + int[] result = new int[n + 1]; + for (int i = 1; i <= n; i++) { + result[i] = result[i >> 1] + (i & 1); + } + return result; + } +} From ccd7b0dbfca4e071e5e5d14b00017de87e3ee782 Mon Sep 17 00:00:00 2001 From: devtkwon Date: Sat, 24 Aug 2024 09:23:49 +0900 Subject: [PATCH 5/6] fix: valid-anagram --- valid-anagram/taekwon-dev.java | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/valid-anagram/taekwon-dev.java b/valid-anagram/taekwon-dev.java index c93377b32..c2b578361 100644 --- a/valid-anagram/taekwon-dev.java +++ b/valid-anagram/taekwon-dev.java @@ -1,13 +1,9 @@ /** - * 시간 복잡도: O(NlogN) - * - Arrays.sort() > Dual-Pivot QuickSort - * - * 공간 복잡도: O(N) - * * 처음 문제를 보고 들었던 생각: 정렬 시켜서 같으면 anagram? - * -> 아, 그러면 등장한 문자의 빈도수가 같네? - * -> 결국 26 사이즈가 인풋에 영향을 받지 않으므로 공간 복잡도를 O(1)로 개선할 수 있고, - * -> 시간 복잡도도 O(N)으로 개선할 수 있겠다. + * 근데, 정렬 시켜서 같다면, 결국 문자열을 구성하는 각 문자의 빈도수가 같다. + * + * 시간 복잡도: O(N) + * 공간 복잡도: O(1) */ class Solution { public boolean isAnagram(String s, String t) { @@ -15,13 +11,14 @@ public boolean isAnagram(String s, String t) { int[] charCount = new int[26]; - for (char c : s.toCharArray()) { - charCount[c - 'a']++; + for (int i = 0; i < s.length(); i++) { + charCount[s.charAt(i) - 'a']++; } - for (char c : t.toCharArray()) { - charCount[c - 'a']--; - if (charCount[c - 'a'] < 0) { + for (int i = 0; i < t.length(); i++) { + int index = t.charAt(i) - 'a'; + charCount[index]--; + if (charCount[index] < 0) { return false; } } From a0fc24d44dd6c3d2e30be588315db93257b35523 Mon Sep 17 00:00:00 2001 From: devtkwon Date: Sat, 24 Aug 2024 10:25:56 +0900 Subject: [PATCH 6/6] construct-binary-tree-from-preorder-and-inorder-traversal with solution-v1 --- .../taekwon-dev.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 construct-binary-tree-from-preorder-and-inorder-traversal/taekwon-dev.java diff --git a/construct-binary-tree-from-preorder-and-inorder-traversal/taekwon-dev.java b/construct-binary-tree-from-preorder-and-inorder-traversal/taekwon-dev.java new file mode 100644 index 000000000..af6a0d65d --- /dev/null +++ b/construct-binary-tree-from-preorder-and-inorder-traversal/taekwon-dev.java @@ -0,0 +1,36 @@ +/** + * https://www.algodale.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ + * + * <풀이1 기준> 시도! + * - 공간 복잡도: O(N^2) - Java 에서는 Call-by-value, 메서드 호출 시 인자 값이 복사되어 전달됨 / 배열 길이에 따라서 재귀 호출 스택이 점점 깊어짐 (각 호출마다 서브 배열 생성) + * - 시간 복잡도: inorder 배열에서 root 노드를 찾아가는 과정이 O(N), 그리고 이를 재귀 호출마다 반복하므로 O(N^2) + */ +class Solution { + public TreeNode buildTree(int[] preorder, int[] inorder) { + return buildTree(preorder, inorder, 0, 0, inorder.length - 1); + } + + private TreeNode buildTree(int[] preorder, int[] inorder, int rootIdx, int inorderStartIdx, int inorderEndIdx) { + if (inorderStartIdx > inorderEndIdx) { + return null; + } + + int rootVal = preorder[rootIdx]; + TreeNode root = new TreeNode(rootVal); + + int rootIdxOnInorder = 0; + for (int i = inorderStartIdx; i <= inorderEndIdx; i++) { + if (inorder[i] == rootVal) { + rootIdxOnInorder = i; + break; + } + } + + int leftLength = rootIdxOnInorder - inorderStartIdx; + + root.left = buildTree(preorder, inorder, rootIdx + 1, inorderStartIdx, rootIdxOnInorder - 1); + root.right = buildTree(preorder, inorder, rootIdx + 1 + leftLength, rootIdxOnInorder + 1, inorderEndIdx); + + return root; + } +}