diff --git a/combination-sum/jinvicky.java b/combination-sum/jinvicky.java new file mode 100644 index 000000000..582de8a7d --- /dev/null +++ b/combination-sum/jinvicky.java @@ -0,0 +1,32 @@ +import java.util.ArrayList; +import java.util.List; + +class Solution { + public List> combinationSum(int[] candidates, int target) { + List> answer = new ArrayList<>(); + + makeCombination(candidates, target, 0, new ArrayList<>(), 0, answer); + return answer; + } + + private void makeCombination(int[] candidates, + int target, + int idx, + List comb, + int total, + List> res) { + if (total == target) { + res.add(new ArrayList<>(comb)); + return; + } + + if (total > target || idx >= candidates.length) { + return; + } + + comb.add(candidates[idx]); + makeCombination(candidates, target, idx, comb, total + candidates[idx], res); + comb.remove(comb.size() - 1); + makeCombination(candidates, target, idx + 1, comb, total, res); + } +} diff --git a/decode-ways/jinvicky.java b/decode-ways/jinvicky.java new file mode 100644 index 000000000..c0333cd16 --- /dev/null +++ b/decode-ways/jinvicky.java @@ -0,0 +1,23 @@ +class Solution { + public int numDecodings(String s) { + if (s.charAt(0) == '0') return 0; + + int n = s.length(); + int[] dp = new int[n+1]; + dp[0] = dp[1] = 1; + + for(int i = 2; i <= n; i++) { + int one = Character.getNumericValue(s.charAt(i-1)); + int two = Integer.parseInt(s.substring(i-2, i)); + + if(1 <= one && one <= 9) { + dp[i] += dp[i-1]; + } + if(10 <= two && two <= 26) { + dp[i] += dp[i-2]; + } + } + + return dp[n]; + } +} diff --git a/maximum-subarray/jinvicky.java b/maximum-subarray/jinvicky.java new file mode 100644 index 000000000..4e78e62ea --- /dev/null +++ b/maximum-subarray/jinvicky.java @@ -0,0 +1,43 @@ +// [참고] +// 카데인 알고리즘: 이전요소의 부분합을 알면 현재요소의 최대값을 알 수 있다. +// 양수만이라면 단순히 dp로 dp[nums.length-1] 값이나 total이라는 계산값을 리턴하겠지만, +// 음수가 포함되었으므로 bestSum과 currentSum을 별개의 변수로 처리한다. +// currentSum은 최대 sum을 구해야 하므로 음수값일때 강제로 0으로 업데이트 후 계산을 실행한다. +// https://velog.io/@wind1992/Leetcode-53.-Maximum-Subarray +// +// [풀이방식] +// 1. 카데인 알고리즘 2. DP +// [성능] +// dp 배열보다 변수를 사용하는 것이 공간 복잡도를 줄일 수 있다. 또한 for문 1개로 해결 가능하다. +class Solution { + public int maxSubArray(int[] nums) { + int bestSum = nums[0]; + int currentSum = 0; + + for (int n : nums) { + if (currentSum < 0) { // 1. 업데이트 + currentSum = 0; + } + + // 2. 계산 + currentSum += n; + bestSum = Math.max(currentSum, bestSum); + } + return bestSum; + } + + public int maxSubArrayDp(int[] nums) { + int n = nums.length; + int[] dp = new int[n]; + + dp[0] = nums[0]; + int maxSum = dp[0]; + + for (int i = 1; i < n; i++) { + dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]); + maxSum = Math.max(maxSum, dp[i]); + } + + return maxSum; + } +} diff --git a/number-of-1-bits/jinvicky.java b/number-of-1-bits/jinvicky.java new file mode 100644 index 000000000..f7c191f62 --- /dev/null +++ b/number-of-1-bits/jinvicky.java @@ -0,0 +1,40 @@ +class Solution { + // [sol1] 반복문을 사용하면서 ((n>>i) & 1) == 1를 만족하는 개수를 구한다. + // n을 변경하지 않지만 [sol1-1]보다 느리다. + public int hammingWeight(int n) { + int answer = 0; + for(int i = 0; i < 32; i++) { + // >> 연산자를 이용하여 값을 오른쪽으로 bitwise 연산을 한다. + if(((n>>i) & 1) == 1) { + answer+=1; + } + } + return answer; + } + + // [sol1-1] n 값이 변경되면서 [sol1]보다 성능이 개선된다. + public int hammingWeight1_1(int n) { + int answer = 0; + for (int i = 0; i < 32; i++) { + answer += (n & 1); + n >>>= 1; + } + return answer; + } + + // [sol2] 자바를 사용한다면 1개의 메서드, 1줄의 코드로 해결할 수 있다. + public int hammingWeight2 (int n) { + return Integer.bitCount(n); + } + + // [sol3] 1의 개수만큼만 반복한다. + // 예) n = 1011 -> 1000 -> 0000 종료 + public int hammingWeight3(int n) { + int answer = 0; + while (n != 0) { + n &= (n - 1); // 가장 오른쪽 1 비트를 0으로 만듦 + answer++; + } + return answer; + } +} diff --git a/valid-palindrome/jinvicky.java b/valid-palindrome/jinvicky.java new file mode 100644 index 000000000..556eb74d0 --- /dev/null +++ b/valid-palindrome/jinvicky.java @@ -0,0 +1,50 @@ +class Solution { + + /** + * 런타임 231ms + * [생각] + * for문으로 알파벳, 숫자를 제외한 특수문자들을 제거한 후에 투 포인터 알고리즘으로 풀이하자. + */ + public boolean isPalindrome(String s) { + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + if (Character.isDigit(c)) { + sb.append(c); + } + if (Character.isAlphabetic(c)) { + sb.append(Character.toLowerCase(c)); + } + } + + int left = 0; + int right = sb.toString().length() - 1; + + while (left <= right) { + if (sb.toString().charAt(left) != sb.toString().charAt(right)) { + return false; + } + left++; + right--; + } + return true; + } + + /** + * 런타임 7ms + * [생각] + * 굳이 투 포인터로? 이미 활용중인 StringBuilder를 reverse()본과 원본을 비교하면 탐색 필요없다. + * 또한 " " 케이스는 사전에 리턴처리한다. + */ + public boolean isPalindrome2(String s) { + if (s.equals(" ")) + return true; + + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isDigit(c)) { + sb.append(Character.toLowerCase(c)); + } + } + return sb.toString().equals(sb.reverse().toString()); + } +}