diff --git a/3sum/dahyeong-yun.java b/3sum/dahyeong-yun.java new file mode 100644 index 0000000000..61d12d376b --- /dev/null +++ b/3sum/dahyeong-yun.java @@ -0,0 +1,53 @@ +/** + * 0. 풀이 개요 + * - 시간복잡도 : O(n^2) + * - 공간복잡도 : O(1) + */ + +class Solution { + /** + * 1. 풀이 과정 + * 1.1 문제 이해 + * - 세 수의 합이 0이 되는 중복 없는 전체 조합 찾기 + * 1.2 제약 사항 + * - 인덱스의 조합이 아닌 값의 조합이므로 배열의 원본을 유지할 필요는 없음 + * - 조합의 중복을 어떻게 제외 시킬지가 관건 + * 1.3 풀이 아이디어 + * - 하나의 값이 고정되어 있으면 나머지 두 원소의 합이 고정값 * -1 이 되어야 하는 형태라고도 볼 수 있음 + * - 배열의 인덱스는 몰라도 되므로 배열을 오름차순으로 정렬할 수 있음 + * - 이때 고정값 하나는 반복문 안에서 루프를 돌면서 정하고, 나머지 두 수는 투 포인터로 원하는 조합을 찾을 수 있음 + * - 배열이 오름차순으로 정렬되어 있으므로, 만약 합이 0 보다 크다면 숫자가 작아져야 하고, 0보다 작다면 숫자가 커져야 함. + * - 따라서 세 수의 합이 작아져야 한다면 우측 포인터를 좌측으로 옮기면서 숫자를 줄일 수 있고, + * - 합이 커져야 한다면 좌측 포인터를 우측으로 옮기면서 전체 합을 키울 수 있음. + * - 여기에 더해 중복을 제외하기 위해서 같은 수의 경우는 포인터를 건너뛰는 식으로 처리할 수 있음. + * - 시간복잡도는 배열의 원소(n)만큼 루프를 돌면서, 그 안에서 최악의 경우 n - 2 번 순회 하게 되므로 N(N-2) 가 되어 n^2 이라 볼 수 있음. + * - 추가적인 공간을 일부 만들기는 하는데 n에 차수에 대응하는 수가 없으므로 공간복잡도는 O(1)로 판단. + */ + public List> threeSum(int[] nums) { + Arrays.sort(nums); + List> answer = new ArrayList<>(); + + for(int i=0; i < nums.length - 2; i++) { + if (i > 0 && nums[i] == nums[i - 1]) { + continue; + } + + int left = i+1; + int right = nums.length - 1; + + while(left < right) { + if(nums[i] + nums[left] + nums[right] == 0) { + List triple = List.of(nums[i], nums[left], nums[right]); + answer.add(triple); + while(left+1 < right && nums[left] == nums[left+1]) left++; + while(right > 0 && nums[right] == nums[right-1]) right--; + left++; + right--; + } else if(nums[i] + nums[left] + nums[right] > 0) right--; + else left++; + } + } + + return answer; + } +} diff --git a/climbing-stairs/dahyeong-yun.java b/climbing-stairs/dahyeong-yun.java new file mode 100644 index 0000000000..218df35a66 --- /dev/null +++ b/climbing-stairs/dahyeong-yun.java @@ -0,0 +1,36 @@ +/** + * 0. 풀이 개요 + * - 시간복잡도 : O(n) + * - 공간복잡도 : O(n) + */ +class Solution { + /** + * 1. 풀이 과정 + * 1.1 이해 + * - n 이 계단 수고 그 계단을 오르는 방법의 가짓 수를 + * 1.2 제약 + * - n이 1부터 45까지 임. + * 1.3 아이디어 + * - 전형적인 DP 로 보이긴 함. + * - 현 단계로 오기 위해서는 전 단계에서 + 1을 하던지 전전단계에서 + 2 하던지 하는 방법이 있음 + * - 즉 전 단계 까지의 가짓 수 + 전전 단계까지의 가짓 수 = 현 단계의 가짓 수 됨 + * - 1번째와 2번째는 전전 단계가 없으므로 직접 계산 해준다. + * - n까지 순회하면서 계산하며, 각 단계의 가짓 수는 O(1)에 조회되므로 시간복잡도는 O(n) 이다. + * - 별도 배열이 n+1 만큼 필요하므로 O(n)의 공간복잡도를 가진다. + * 2. 최적화 + * - 각 단계의 숫자는 계속 가지고 있을 필요 없이 별도 변수로 처리하면 공간복잡도를 O(1)로 최적화 할 수 있다. + */ + public int climbStairs(int n) { + if(n == 1) return 1; + if(n == 2) return 2; + + int[] steps = new int[n+1]; + steps[1] = 1; + steps[2] = 2; + + for(int i=3; i<=n; i++) { + steps[i] = steps[i-1] + steps[i-2]; + } + return steps[n]; + } +} diff --git a/product-of-array-except-self/dahyeong-yun.java b/product-of-array-except-self/dahyeong-yun.java new file mode 100644 index 0000000000..ffe557acc4 --- /dev/null +++ b/product-of-array-except-self/dahyeong-yun.java @@ -0,0 +1,43 @@ +/** + * 0. 풀이 개요 + * - 시간복잡도 : O(n) + * - 공간복잡도 : O(n) + */ +class Solution { + /** + * 1. 풀이 과정 + * 1.1 이해 + * - 각 배열의 원소가 본인을 제외한 모든 것이 곱해진 상태를 출력하면 됨. + * 1.2 제약 + * - n이 2부터 10^5까지 임. 배열을 순회하는 경우 n^2은 어려워 보임(10^8 기준). 따라서 n log n 이하가 필요 + * 1.3 아이디어 + * - 사실 문제를 몇번 풀었어서 외워져 버림 + * - 시각적으로 보이자면 2개의 배열을 활용하는 셈 + * - | 배열 원소를 변수로 치환 | a | b | c | d | + * | prefix 의 상태 | 1 | 1 * a = a | a * b = ab | ab * c = abc | + * | suffix 의 상태 | bcd | cd | d | 1 | + * | prefix * suffix | bcd | acd | abd | abc | + * - 시간복잡도는 n 번씩 두번 순회 하므로 2n 번 순회로 O(n)이 됨. + * - 공간복잡도는 n 크기 만큼의 배열을 추가로 생성하므로 O(n)이 됨. + */ + public int[] productExceptSelf(int[] nums) { + int prefix = 1; + int suffix = 1; + + int len = nums.length; + int[] answer = new int[len]; + + answer[0] = 1; + for(int i = 1; i < len; i++) { + answer[i] = prefix * nums[i-1]; + prefix *= nums[i-1]; + } + + for(int i = len-1; i >= 0; i--) { + answer[i] = answer[i] * suffix; + suffix *= nums[i]; + } + + return answer; + } +} diff --git a/valid-anagram/dahyeong-yun.java b/valid-anagram/dahyeong-yun.java new file mode 100644 index 0000000000..5926faafd9 --- /dev/null +++ b/valid-anagram/dahyeong-yun.java @@ -0,0 +1,28 @@ +/** + * 0. 풀이 개요 + * - 시간복잡도 : O(n log n) + * - 공간복잡도 : O(n) + */ +class Solution { + /** + * 1. 풀이 과정 + * 1.1 문제 이해 + * - 애너그램이 가능한 문자열인지 판단하는 문제임. 두 문자열 s와 t가 주어지고, t가 s의 애너그램이라면 true를 반환 + * 1.2 제약 사항 + * - s, 와 t의 문자열의 길이가 5 * 10^4 이므로 문자열 길이 만큼 순회해야 한다면 O(n^2)은 불가능해 보임. O(n log n) 이하가 필요. + * - 문자는 반드시 영소문자로만 구성되어 있으나, 만약 Follow up 질문 처럼 유니코드를 포함해야 된다면 이를 포괄하는 자료형이 필요. + * 1.3 풀이 아이디어 + * - 문자열을 정렬했을 때, 같은 문자열이라면 애너그램이 될 것. + * - 문자열의 character를 배열로 만들고 정렬하면, bulit-in 메서드에 의해 O(n log n)의 시간복잡도가 가짐, + * - 문자열의 길이만큼 character 배열이 필요하므로 2n 만큼의 공간이 더 필요하므로 O(n)의 공간복잡도를 가짐. + */ + public boolean isAnagram(String s, String t) { + char[] arrayS = s.toCharArray(); + char[] arrayT = t.toCharArray(); + + Arrays.sort(arrayS); + Arrays.sort(arrayT); + + return Arrays.equals(arrayS, arrayT); + } +} diff --git a/validate-binary-search-tree/dahyeong-yun.java b/validate-binary-search-tree/dahyeong-yun.java new file mode 100644 index 0000000000..e919fd8957 --- /dev/null +++ b/validate-binary-search-tree/dahyeong-yun.java @@ -0,0 +1,28 @@ +/** + * 0. 풀이 개요 + * - 시간복잡도 : O(n log n) + * - 공간복잡도 : O(n) + */ +class Solution { + /** + * 1. 풀이 과정 + * 1.1 문제 이해 + * - 애니어그램이 가능한 문자열인지 판단하는 문제임. 두 문자열 s와 t가 주어지고, t가 s의 애니어그램이라면 true를 반환 + * 1.2 제약 사항 + * - s, 와 t의 문자열의 길이가 5 * 10^4 이므로 문자열 길이 만큼 순회해야 한다면 O(n^2)은 불가능해 보임. O(n log n) 이하가 필요. + * - 문자는 반드시 영소문자로만 구성되어 있으나, 만약 Follow up 질문 처럼 유니코드를 포함해야 된다면 이를 포괄하는 자료형이 필요. + * 1.3 풀이 아이디어 + * - 문자열을 정렬했을 때, 같은 문자열이라면 애니어그램이 될 것. + * - 문자열의 character를 배열로 만들고 정렬하면, bulit-in 메서드에 의해 O(n log n)의 시간복잡도가 가짐, + * - 문자열의 길이만큼 character 배열이 필요하므로 2n 만큼의 공간이 더 필요하므로 O(n)의 공간복잡도를 가짐. + */ + public boolean isAnagram(String s, String t) { + char[] arrayS = s.toCharArray(); + char[] arrayT = t.toCharArray(); + + Arrays.sort(arrayS); + Arrays.sort(arrayT); + + return Arrays.equals(arrayS, arrayT); + } +}