diff --git a/contains-duplicate/haxr369.java b/contains-duplicate/haxr369.java new file mode 100644 index 000000000..ba92b61a6 --- /dev/null +++ b/contains-duplicate/haxr369.java @@ -0,0 +1,27 @@ +import java.util.HashSet; +import java.util.Set; + +class Solution { + public boolean containsDuplicate(int[] nums) { + /** + * Runtime: 14 ms (Beats 62.49%) + * Space Complexity: O(N) + * > nums 배열 길이 N. 중복하지 않은 모든 요소가 Set에 들어가기 때문에 O(N) + * Time Complexity: O(N) ~ O(NlogN) + * - 크기 N 배열 조회에 O(N) + * - Set에 숫자 중복 체크 O(1) + * - 단, 최악에 경우로 중복 체크에 O(logN)이 발생 가능 + * > O(N) * O(1) ~ O(NlogN) + * Memory: 93.28 (Beats 6.24%) + */ + Set st = new HashSet<>(); + for (int n : nums) { + if (st.contains(n)) { + return true; + } + st.add(n); + } + return false; + + } +} diff --git a/house-robber/haxr369.java b/house-robber/haxr369.java new file mode 100644 index 000000000..0e577d1b6 --- /dev/null +++ b/house-robber/haxr369.java @@ -0,0 +1,41 @@ +class Solution { + /** + * 인전합 두 집을 털면 안됨 + * + * i번째 집에서 할 수 있는 행위는? 2가지. + * 털거나: + * 털면 i-1번째 집은 안 털어야함, i-2번째 집은 털어도 괜찮겠지? + * Money_A = nums[i] + DP[i-2] + * 털지 않거나: + * i번째 집을 안 털면, i-1번째집은 털어도 괜찮다. + * Money_B = DP[i-1] + * dp[i]를 i번째 집 앞에서 들고 있을 최대 금액이라고 할 때, + * dp[i] = MAX(Money_A, Money_B) + * 문제는 dp[nums.length-1]을 구하기 + */ + public int rob(int[] nums) { + /** + * 12분 소요. + * Runtime: 0 ms (Beats 100%) + * Memory: 42.74 MB (Beats 6.31%) + * Space Complexity: O(N) + * - nums 저장 => O(N) + * - 최대 금액 저장 배열 => O(N) + * > O(2N) ~= O(N) + * Time Complexity: O(N) + * - nums 처음부터 끝까지 조회하며 dp 저장. => O(N) + * > O(N) + */ + int[] dp = new int[nums.length]; + + dp[0] = nums[0]; + if (nums.length > 1) { + dp[1] = Integer.max(dp[0], nums[1]); + } + for (int i = 2; i < nums.length; i++) { + // 터는 경우와 안터는 경우 중 최대 값. + dp[i] = Integer.max(dp[i - 2] + nums[i], dp[i - 1]); + } + return dp[nums.length - 1]; + } +} diff --git a/longest-consecutive-sequence/haxr369.java b/longest-consecutive-sequence/haxr369.java new file mode 100644 index 000000000..6fff1e723 --- /dev/null +++ b/longest-consecutive-sequence/haxr369.java @@ -0,0 +1,37 @@ +import java.util.Arrays; + +class Solution { + /** + * 13분 소요. + * Runtime: 23 ms (Beats 80.31%) + * Memory: 77.33 (Beats 9.66%) + * Space Complexity: O(N) + * - 원소 배열 정렬은 듀얼 피봇 sort => O(logN) + * > O(N) + O(logN) ~= O(N) + * Time Complexity: O(NlogN) + * - 듀얼 피봇 sort를 이용한 정렬 => O(NlogN) + * - 배열을 처음부터 끝까지 조회, 이전 값과 비교 => O(N)*O(1) + * > O(NlogN) + O(N) ~= O(NlogN) + */ + public int longestConsecutive(int[] nums) { + Arrays.sort(nums); + + if (nums.length == 0) { + return 0; + } + int ans = 1; + int seqLgth = 1; + for (int i = 1; i < nums.length; i++) { + // 바로 연결되는 경우는 바로 이전 요소 보다 1이 더 커야함. + if (nums[i - 1] < nums[i] && nums[i] - nums[i - 1] == 1) { + nums[i - 1] = nums[i]; + seqLgth++; + ans = Integer.max(ans, seqLgth); // 항상 ans 업데이트 하기 + } else if (nums[i - 1] < nums[i] && nums[i] - nums[i - 1] > 1) { + // 새로운 연결로 들어가기 + seqLgth = 1; + } + } + return ans; + } +} diff --git a/top-k-frequent-elements/haxr369.java b/top-k-frequent-elements/haxr369.java new file mode 100644 index 000000000..a7b3e465e --- /dev/null +++ b/top-k-frequent-elements/haxr369.java @@ -0,0 +1,50 @@ +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +class Solution { + /** + * 30분 38초 소요. + * nums에서 가장 자주 등장하는 k개 숫자 리턴하기 + * Map에 요소:등장수로 관리하기 + * Stream으로 등장수 기준으로 내림차순 정렬 후 k개만 리스트로 만들어서 출력한다. + * + * Java의 Stream과 Comparator 사용법을 익혀야함. + * Comparable도 몰랐던 부분. + */ + public int[] topKFrequent(int[] nums, int k) { + /** + * Runtime: 21 ms (Beats 6.30%) + * Memory: 47.42 (Beats 83.73%) + * Space Complexity: O(N) + * - HashMap 공간복잡도 => O(N) + * - sort에서 tim sort 사용 => O(N) + * > O(N) + * Time Complexity: O(NlogN) + * - tim sort를 이용한 정렬 => O(NlogN) + * > O(N) + O(NlogN) + O(N) ~= O(NlogN) + */ + + Map mp = new HashMap<>(); + for (int n : nums) { + if (mp.containsKey(n)) { + mp.put(n, mp.get(n) + 1); + } else { + mp.put(n, 1); + } + } + List li = mp.entrySet().stream() + // 값을 기준으로 내림차순 정렬 + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(k) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + int[] ans = new int[li.size()]; + for (int i = 0; i < li.size(); i++) { + ans[i] = li.get(i); + } + return ans; + } +} diff --git a/two-sum/haxr369.java b/two-sum/haxr369.java new file mode 100644 index 000000000..6efc65cf5 --- /dev/null +++ b/two-sum/haxr369.java @@ -0,0 +1,57 @@ +import java.util.Arrays; + +class Solution { + /** + * 합해서 target이 되는 두 수의 인덱스를 배열에 넣어서 return. + * 1. nums 정렬하기 + * 2. smlNumbIdx(초기 0), lrgNumbIdx(초기 nums.length - 1)에 인덱스를 저장 + * 3. smlNumb와 lrgNumb를 합해서 tmp를 계산 + * 4. tmp와 target을 비교. + * 4.1. tmp < target인 경우 + * smlNumbIdx에 1 더하기 + * 4.2. tmp > target인 경우 + * lrgNumbIdx에 1 빼기 + * 4.3. tmp = target인 경우 + * smlNumbIdx와 lrgNumbIdx 배열 return + */ + public int[] twoSum(int[] nums, int target) { + /** + * Runtime: 8 ms (Beats 47.90%) + * Memory: 46.70 (Beats 5.05%) + * Space Complexity: O(N) + * > Arrays.sort의 객체 타입은 tim sort를 이용하기 때문에 O(N)을 가짐 + * Time Complexity: O(NlogN) + * - 크기 Nx2 배열에 값과 인덱스를 넣기 => O(N) + * - tim sort를 이용한 정렬 => O(NlogN) + * - N회 for문으로 정답 인덱스 찾기 => O(N) + * > O(N) + O(NlogN) + O(N) ~= O(NlogN) + */ + int[][] arr = new int[nums.length][2]; + for (int i = 0; i < nums.length; i++) { + arr[i][0] = nums[i]; + arr[i][1] = i; + } + Arrays.sort(arr, (a, b) -> { + if (a[0] != b[0]) + return Integer.compare(a[0], b[0]); + return 1; // 동일하면 상관 없음. + }); + + int smlNumbIdx = 0; + int lrgNumbIdx = nums.length - 1; + for (int i = 0; i < arr.length; i++) { + if (arr[smlNumbIdx][0] + arr[lrgNumbIdx][0] == target) { + int[] ans = { arr[smlNumbIdx][1], arr[lrgNumbIdx][1] }; + return ans; + } else if (arr[smlNumbIdx][0] + arr[lrgNumbIdx][0] < target) { + smlNumbIdx++; + } else { + lrgNumbIdx--; + } + } + + // 문제는 없지만, 예외케이스가 발생할 수 있으니 더미 데이터 출력 + int[] ans = { 0, nums.length }; + return ans; + } +}