diff --git a/combination-sum/grapefruitgreentealoe.js b/combination-sum/grapefruitgreentealoe.js new file mode 100644 index 000000000..de13fa323 --- /dev/null +++ b/combination-sum/grapefruitgreentealoe.js @@ -0,0 +1,93 @@ +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ + +/** + * candidates를 여러번 사용해도 된다. 하지만 사용한 종류와 개수가 모두 같으면 안된다. + * + */ +var combinationSum = function(candidates, target) { + const candidatesLength = candidates.length + // 시작 시점에서 array를 만들어서 넘겨줘야한다. + // candidates 중에 넣으면 target이 되면 답에 그 배열을 넣고 탈출한다. + // 만약 더했는데 target보다 크면 그냥 리턴한다. + // target보다 작은것에 대해서 넣는다. + const ret = [] + function dp(total,newNum,currentArr){ + if(total + newNum > target){ + return + } + if(total + newNum == target && ){ + ret.push([...currentArr,newNum]); + return + } + + //두 가지 어느것에도 해당하지 않으면 재귀를 또 다시 돈다. + for(let i = 0; i target){ + return + } + if(total == target){ + ret.push(currentArr); + return + } + + //idx를 넘겨받아서, 그 이후의 것에만(자기 자신 포함) 돌게 된다. 그러면 절반정도만 돈다고 볼 수 있다. + for(let i = idx; i < candidatesLength; i++){ + dp(i,total+ candidates[i],[...currentArr,candidates[i]]) + } + } + dp(0,0,[]) + return ret +}; + + + +/** + 시간복잡도: O(N^(target/min)) : N개 후보 중 선택하는 경우의 수가 target/min 깊이만큼 반복 +공간복잡도: O(target/min) : 재귀 스택의 최대 깊이가 target/min + + + */ + + +// 2. dp를 활용한 문제 해결방법 +var combinationSum = function(candidates, target) { + const dp = Array.from({length:target+1},()=>[]) + dp[0] = [[]]; + for(let candidate of candidates){ + //여기서 candidate에 대해서, 이후 타겟까지 더할 수있는 숫자에 대한 조합에, candidate를 각각 넣어준다. + for(let i = candidate; i <= target; i++){ + for(let comb of dp[i-candidate]){ //각 조합에 넣어줌 + dp[i].push([...comb,candidate]) + } + } + } + return dp[target] +}; +/** +시간복잡도: O(N × target × M) +N개 후보를 순회하면서, 각 후보마다 target까지의 값들에 대해 기존 조합들을 복사해서 새 조합을 생성하는데, 기존의 조합의 수 M을 곱해야함 +공간복잡도: O(target × M) +dp 배열의 각 인덱스에 해당 값을 만드는 모든 조합들을 저장. 조합개수에 따라서 커짐 + */ diff --git a/decode-ways/grapefruitgreentealoe.js b/decode-ways/grapefruitgreentealoe.js new file mode 100644 index 000000000..14b3c9ebd --- /dev/null +++ b/decode-ways/grapefruitgreentealoe.js @@ -0,0 +1,28 @@ +var numDecodings = function(s) { + if (s[0] === '0') return 0; + + const n = s.length; + const dp = new Array(n + 1).fill(0); + dp[0] = 1; // 빈 문자열. 계단의 첫 시작부분에 1을 넣어주는 것 처럼 + dp[1] = 1; // 첫 글자가 0이 아님은 위에서 확인 + //위 두 값이 기반이 되어 각 자리에 대한 + + for (let i = 2; i <= n; i++) { + const one = Number(s.slice(i - 1, i)); // 한 글자 + const two = Number(s.slice(i - 2, i)); // 두 글자 + + if (one >= 1 && one <= 9) { + dp[i] += dp[i - 1]; + } + if (two >= 10 && two <= 26) { //두자리수 일 때는 dp[i-2]도 더해준다. + dp[i] += dp[i - 2]; + } + // 각 자리의 값(dp[i])은, 1글자 디코딩 시 바로 전 자리(dp[i-1])의 값과, 2글자 디코딩 시 두 자리 전(dp[i-2])의 값을 더해서 만든다. dp[i]는 도착지의 개념같은 것 + + } + + return dp[n]; +}; + +//시간 복잡도: O(n) +//공간 복잡도: O(n) diff --git a/maximum-subarray/grapefruitgreentealoe.js b/maximum-subarray/grapefruitgreentealoe.js new file mode 100644 index 000000000..ba8bc8919 --- /dev/null +++ b/maximum-subarray/grapefruitgreentealoe.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var maxSubArray = function(nums) { + //카데인 알고리즘 + let currentSum = nums[0] + let maxSum = nums[0] + for(let i = 1; ix.isAlphaNum()).map(x=>x.toLowerCase()) + //그 다음엔 index를 양쪽에서 비교하기 + for(let i=0;i<(ss.length/2);i++){ + console.log(ss[i],ss[ss.length-1-i]) + if(ss[i]!==ss[ss.length-1-i]) return false + } + return true +}; + +// 시간 복잡도 O(N) +// 공간 복잡도 O(N) + +//2. 투포인터 방식으로, 필터링과 string 메서드를 그때마다 사용하는 방식으로 효율성 올리기 +var isPalindrome = function(s) { + let left = 0; + let right = s.length - 1; + //각 포인터가 영숫자 문자를 만날 때까지 이동 + while (left < right) { + while (left < right && !s[left].isAlphaNum()) { + left++; + } + while (left < right && !s[right].isAlphaNum()) { + right--; + } + if (left < right && s[left].toLowerCase() !== s[right].toLowerCase()) { + return false; + } + left++; + right--; + } + + return true; +}; + +// 시간 복잡도 O(N) +// 공간 복잡도 O(1) + +/* +더 효율적이게 푸는 방법 +1. String.prototype 확장 지양 +성능적인 측면에서 String.prototype 메서드 호출이 직접적인 헬퍼 함수 호출보다 아주 미세하게 오버헤드가 있을 수 있다 (실제로는 거의 무시할 수 있는 수준) + +2. isAlphaNum 내부 로직 최적화 (Micro-optimization) +- 정규 표현식 엔진이 내부적으로 파싱되고 컴파일되는 오버헤드가 있기 때문에, 정규 표현식, 단순한 문자 범위 체크에는 문자 코드(char code) 비교가 더 빠를 수 있다. + +*/