diff --git a/combination-sum/imsosleepy.java b/combination-sum/imsosleepy.java new file mode 100644 index 000000000..399f0a182 --- /dev/null +++ b/combination-sum/imsosleepy.java @@ -0,0 +1,26 @@ +// 처음엔 dp라 생각했는데, backtracking인걸 알아차리자마자 풀 수 있었음 +// 중간 결과를 계속 전달하는게 팁 +class Solution { + public List> combinationSum(int[] candidates, int target) { + List> result = new ArrayList<>(); + backtracking(candidates, target, 0, new ArrayList<>(), result); + return result; + } + + private void backtracking(int[] candidates, int target, int start, List tmp, List> result) { + if (target < 0) { + return; + } + + if (target == 0) { + result.add(new ArrayList<>(tmp)); + return; + } + + for (int i = start; i < candidates.length; i++) { + tmp.add(candidates[i]); + backtracking(candidates, target - candidates[i], i, tmp, result); + tmp.remove(tmp.size() - 1); + } + } +} diff --git a/maximum-subarray/imsosleepy.java b/maximum-subarray/imsosleepy.java new file mode 100644 index 000000000..a6d977b22 --- /dev/null +++ b/maximum-subarray/imsosleepy.java @@ -0,0 +1,16 @@ +// subarray = "연속된 값"의 합을 요구 함 그래서 간단한 풀이가 가능하다. +// 이전 인덱스나 값들을 기억할 필요가 없어서 누적합 느낌으로 풀 수 있다. +// 키포인트는 이전까지의 합보다 다음 숫자가 큰 경우의 수가 존재한다는 것 +class Solution { + public int maxSubArray(int[] nums) { + int max = nums[0]; + int current = nums[0]; + + for (int i = 1; i < nums.length; i++) { + current = Math.max(nums[i], current + nums[i]); + max = Math.max(max, current); + } + + return max; + } +} diff --git a/product-of-array-except-self/imssoleepy.java b/product-of-array-except-self/imssoleepy.java new file mode 100644 index 000000000..9b7edc0f6 --- /dev/null +++ b/product-of-array-except-self/imssoleepy.java @@ -0,0 +1,20 @@ +class Solution { + // 누적곱을 이용한 풀이 int 크기를 보장해줘서 int를 사용하면된다. + // O(N)의 시간복잡도가 나온다. + public int[] productExceptSelf(int[] nums) { + int n = nums.length; + int[] result = new int[n]; + result[0] = 1; + for (int i = 1; i < n; i++) { + result[i] = result[i - 1] * nums[i - 1]; + } + + int right = 1; + for (int i = n - 1; i >= 0; i--) { + result[i] = result[i] * right; + right *= nums[i]; + } + + return result; + } +} diff --git a/reverse-bits/imsosleepy.java b/reverse-bits/imsosleepy.java new file mode 100644 index 000000000..38f272bb5 --- /dev/null +++ b/reverse-bits/imsosleepy.java @@ -0,0 +1,23 @@ +// 스택으로 풀기보다 비트연산자로 풀이 +// 스택을 사용할 때는 32자리의 불필요한 공간이 생긴다. +public class Solution { + public int reverseBits(int n) { + // n 이 십진수로 들어온다.(중요) + int result = 0; + for (int i = 0; i < 32; i++) { + // 마지막 비트 확인 + // 홀수: 마지막 비트가 1 (n & 1 == 1) + // 짝수: 마지막 비트가 0 (n & 1 == 0) + int bit = n & 1; + // result를 왼쪽으로 1비트 이동하고, 추출한 비트를 추가 + // - result의 마지막 비트를 비우고 (<< 1) + // - OR 연산(|)으로 추출한 비트를 추가 + result = (result << 1) | bit; + + // n을 오른쪽으로 1비트 이동하여 다음 비트를 준비 + // - n의 마지막 비트를 버리고, 상위 비트를 아래로 이동 + n >>= 1; + } + return result; + } +} diff --git a/two-sum/imsosleepy.java b/two-sum/imsosleepy.java new file mode 100644 index 000000000..7ff6f1019 --- /dev/null +++ b/two-sum/imsosleepy.java @@ -0,0 +1,59 @@ +// hashmap 조회 방식은 O(N) +// 3ms +public int[] twoSum(int[] nums, int target) { + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + int complement = target - nums[i]; + if (map.containsKey(complement)) { + return new int[] { map.get(complement), i }; + } + map.put(nums[i], i); + } + return null; +} + +// 첫 생각 : 정렬 -> 투포인터 +public int[] twoSum1(int[] nums, int target) { + Arrays.sort(nums); + int left = 0; + int right = nums.length-1; + int sum = 0; + while(left < right) { + sum = nums[left] + nums[right]; + if(target > sum) { + left++; + } + if(target < sum) { + right--; + } + if(target == sum) { + break; + } + } + return new int[]{left, right}; +} + +// 투포인터는 O(N)에 충족하지만 정렬이 nlog(n)임 +// 9ms +public int[] twoSum2(int[] nums, int target) { + int[][] indexedNums = new int[nums.length][2]; + for (int i = 0; i < nums.length; i++) { + indexedNums[i][0] = nums[i]; + indexedNums[i][1] = i; + } + + Arrays.sort(indexedNums, Comparator.comparingInt(a -> a[0])); + + int left = 0, right = nums.length - 1; + while (left < right) { + int sum = indexedNums[left][0] + indexedNums[right][0]; + if (sum == target) { + return new int[] { indexedNums[left][1], indexedNums[right][1] }; + } else if (sum < target) { + left++; + } else { + right--; + } + } + return new int[]{left, right}; +}