Skip to content

Commit

Permalink
Merge pull request #352 from naringst/main
Browse files Browse the repository at this point in the history
[나리] WEEK 02 Solutions
  • Loading branch information
naringst authored Aug 26, 2024
2 parents d0eed34 + f449a1e commit 521c00b
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* [Idea]
* preorder는 val -> left -> right
* inorder는 left -> val -> right
* 따라서 preorder의 val을 기준으로 inorder 배열을 왼, 오로 나누면 val의 왼쪽 트리, 오른쪽 트리 구조가 된다.
*
* node.val = preorder[i]
* const leftAndRight = inorder.split(preorder[0])
* node.left = leftAndRight[0]
* node.right = leftAndRight[1]
*
* 구현이 안되어 코드 참고 ...
* 직접 배열을 나누지 않고, val의 인덱스를 찾아 그 값을 기준으로 slice된 배열을 재귀적으로 buildTree에 넣는다.
*
*/

var buildTree = function (preorder, inorder) {
if (preorder.length === 0 || inorder.length === 0) {
return null;
}
const root = new TreeNode(preorder[0]);
const rootIndex = inorder.indexOf(root.val);
root.left = buildTree(
preorder.slice(1, rootIndex + 1),
inorder.slice(0, rootIndex)
);
root.right = buildTree(
preorder.slice(rootIndex + 1, preorder.length),
inorder.slice(rootIndex + 1, inorder.length)
);
return root;
};
61 changes: 61 additions & 0 deletions counting-bits/naringst.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @param {number} n
* @return {number[]}
*/

/**
* Runtime: 82ms, Memory: 57.03MB
*
* Time complexity: O(logN < N+1 ? N+1 : logN 단,보통의 경우 N+1)
* Space complexity: O(N+1)
*
* Note: necessary to think of an alternative approach
* **/

function decimalToBinary(decimal) {
let binaryBitCount = 0;

while (decimal > 1) {
binaryBitCount += decimal % 2 === 1 ? 1 : 0;
decimal = Math.floor(decimal / 2);
}
binaryBitCount += decimal === 1 ? 1 : 0;

return binaryBitCount;
}
var countBits = function (n) {
const answer = [];

for (let i = 0; i < n + 1; i++) {
answer.push(decimalToBinary(i));
}

return answer;
};

/**
* 인상 깊었던 풀이
*
* Runtime : 60ms
*
* 비트 연산의 속성과 dp를 활용해 푼 풀이
*
* [간단설명]
* 4일때 100이고, 5일때 101, 6일때 110이다.
* 이때 4를 2진수로 표현한 100이 가진 1의 개수를 활용해 5,6의 1의 개수를 찾는 것이다.
* 100에서 1을 더한 101이나, 110은 100의 1의 개수인 1개에서 1을 더한 2개가 된다.
* result[5 & 4] => 비트 연산을 통해 100과 101의 비트 앤드 연산을 해서 100이 되고, 이는 101의 가장 오른쪽 1을 제거한 값이 된다.
* result[6 & 5] => 비트 연산을 통해 110과 101의 비트 앤드 연산을 해서 100이 되고, 이는 110의 가장 오른쪽 1을 제거한 값이 된다.
* 이진수는 1씩 더하기 때문에 나보다 하나 큰 수와 앤드 연산을 하면 작은 수가 0으로 끝나면 큰 수는 1로 끝나고,
* 작은 수가 1로 끝나면 큰 수는 0으로 끝나기 대문에 이런 속성을 갖는다.
*
*
*/

var countBits = function (n) {
let result = new Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
result[i] = result[i & (i - 1)] + 1;
}
return result;
};
65 changes: 65 additions & 0 deletions decode-ways/naringst.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* 답안 참고 풀이
* 💡 왜 못풀었을까?
* 한 자리, 두 자리 경우 중 가능한 경우에 대해 조건 분기를 제대로 못했음.
*/

var numDecodings = function (s) {
const dp = Array(s.length + 1).fill(0);

// 예외 처리
if (s[0] === "0") return 0;

dp[0] = 1;
dp[1] = 1;

for (let i = 2; i <= s.length; i++) {
// 1자리 값 , 2자리 값 파싱
const oneDigit = +s.slice(i - 1, i);
const twoDigits = +s.slice(i - 2, i);
// 각 값이 가능한지 판단: 여기를 제대로 식을 세우지 못했음
if (oneDigit > 0) dp[i] = dp[i - 1];
if (twoDigits >= 10 && twoDigits <= 26) dp[i] += dp[i - 2];
}
return dp[s.length];
};

/**
* 처음 떠올렸던 방식인 dp로는 풀기 어려울 것 같아 풀이를 다시 생각해 봄.
* 문자를 만드는 걸 숫자를 칸막이로 나누는 개념으로 생각. ex) 2/5/2/4, 2/52/4
* 그러면 숫자와 숫자 사이 칸막이를 넣을지, 말지의 문제로 귀결
* 2의 (s.length-1)제곱의 경우의 수 발생
* 그 중 안되는 경우를 제외하면 답이 됨.
* */

/**
* @param {string} s
* @return {number}
*/

/**
* NOTE 첫 풀이 -> 잘못된 풀이
* dp를 사용해서 한자리씩, 그리고 다음 자릿수와 함께 두 자리 씩 확인해 경우의 수를 추가하면 된다고 생각했는데,
* 2101과 같은 경우에 동작하지 않음.
*
* */

var numDecodings = function (s) {
let dp = Array(s.length).fill(0);

// 시작 숫자가 0이면 불가능 -> 예외 처리
if (s[0] !== "0") {
dp[0] = 1;
} else {
return 0;
}

for (let i = 0; i < s.length; i++) {
if (i !== s.length - 1 && Number(s[i] + s[i + 1]) <= 26 && s[i] !== "0") {
dp[i + 1] = dp[i] + 1;
} else if (s[i + 1] === "0" || Number(s[i] + s[i + 1]) > 26) {
dp[i + 1] = dp[i];
}
}
return dp[s.length - 1];
};
74 changes: 74 additions & 0 deletions valid-anagram/naringst.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/

/**
* Runtime: 68ms, Memory: 54.49MB
* n = s.length > t.length ? s.length : t.length
* Time complexity: O(n)
* Space complexity: O(n)
*
* **/

function arrayToDict(arr) {
const dict = {};
for (let element of arr) {
if (dict[element]) {
dict[element] += 1;
} else {
dict[element] = 1;
}
}
return dict;
}

function isSameDict(dict1, dict2) {
if (Object.keys(dict1).length !== Object.keys(dict2).length) {
return false;
}

for (const elem in dict1) {
if (dict1[elem] !== dict2[elem]) {
return false;
}
}
return true;
}

var isAnagram = function (s, t) {
const sArr = [...s];
const tArr = [...t];

const sDict = arrayToDict(sArr);
const tDict = arrayToDict(tArr);

return isSameDict(sDict, tDict);
};

/**
* 같은 로직인데 53ms 걸린 다른 풀이
*/

var isAnagram = function (s, t) {
if (s.length !== t.length) {
return false;
}

const countA = {};
const countB = {};

for (let i = 0; i < s.length; i++) {
countA[s[i]] = 1 + (countA[s[i]] || 0);
countB[t[i]] = 1 + (countB[t[i]] || 0);
}

for (const key in countA) {
if (countA[key] !== countB[key]) {
return false;
}
}

return true;
};

0 comments on commit 521c00b

Please sign in to comment.