-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[mallayon] Week 2 #717
Merged
Merged
[mallayon] Week 2 #717
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ab0e555
add solution : 338. Counting Bits
mmyeon 171f3b2
remove solution for wrong problem
mmyeon d62602e
add solution : 70. Climbing Stairs
mmyeon b34009a
add solution : 242. Valid Anagram
mmyeon 0e886e0
add solution : 15. 3Sum
mmyeon 4a59c36
add solution : 105. Construct Binary Tree from Preorder and Inorder T…
mmyeon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* | ||
* 접근 방법 : | ||
* - 3개의 숫자를 더한 값이 0이 되는 숫자의 조합 찾는 문제 | ||
* - for문과 투 포인터 사용해서 숫자 조합 찾도록 접근 | ||
* - 투 포인터 이동 조건을 정하기 위해서 배열 오름차순으로 정렬 | ||
* - 합이 0보다 크면 오른쪽 포인터 1 감소하고, 0보다 작으면 왼쪽 포인터 1 증가 | ||
* - 합이 0인 경우에는, 결과값에 조합 저장하고, 포인터 2개 모두 이동시키기 | ||
* - 조합 중복 제거하기 위해서, 첫 번째 숫자와 두 세 번째 숫자 지정할 때 값 같은지 체크해서 같으면 다음 숫자로 넘어가도록 처리 | ||
* | ||
* 시간복잡도 : O(n^2) | ||
* - 배열 정렬 O(nlogn) | ||
* - for문 순회하고 내부에서 while문으로 요소 모두 순회하니까 O(n^2) | ||
* | ||
* 공간복잡도 : | ||
* - 포인터 변수, sum 변수만 사용해서 O(1) | ||
* | ||
* 배운 점 : | ||
* - Set을 활용해서 마지막에 중복 제거하려고 했는데 참조값이라서 원하는대로 동작 안했다. 결과값에 추가하고 중복 제거하는 것보다 추가하기 이전에 중복 제거하는 방식 고려해보기. | ||
*/ | ||
|
||
function threeSum(nums: number[]): number[][] { | ||
const result: number[][] = []; | ||
// 투 포인터 사용하기 위해서 배열 정렬 | ||
nums.sort((a, b) => a - b); | ||
|
||
for (let i = 0; i < nums.length - 2; i++) { | ||
// 중복 조합 제거하기 위해서 같은 값인 경우 넘어가도록 처리 | ||
if (i > 0 && nums[i] === nums[i - 1]) continue; | ||
|
||
let leftPointer = i + 1, | ||
rightPointer = nums.length - 1; | ||
|
||
while (leftPointer < rightPointer) { | ||
const sum = nums[i] + nums[leftPointer] + nums[rightPointer]; | ||
|
||
if (sum < 0) leftPointer++; | ||
else if (sum > 0) rightPointer--; | ||
else { | ||
result.push([nums[i], nums[leftPointer], nums[rightPointer]]); | ||
|
||
// 중복 조합 제거하기 위해서 같은 값인 경우 넘어가도록 처리 | ||
while ( | ||
leftPointer < rightPointer && | ||
nums[leftPointer] === nums[leftPointer + 1] | ||
) | ||
leftPointer++; | ||
while ( | ||
leftPointer < rightPointer && | ||
nums[rightPointer] === nums[rightPointer - 1] | ||
) | ||
rightPointer--; | ||
leftPointer++; | ||
rightPointer--; | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* | ||
* 접근 방법 : dp 사용 | ||
* - 3번째 스텝부터 이전 값 2개의 합으로 구할 수 있다. | ||
* - 반복문을 통해서, 저장해놓은 이전값의 합으로 현재값 구하기 | ||
* - 다음값 구하기 위해서, 이전값을 이전이전값으로, 현재값을 이전값으로 업데이트해주기 | ||
* - 현재값 리턴하기 | ||
* | ||
* 시간복잡도 : | ||
* - 0부터 주어진 n번째스텝까지 순회해야 하므로 O(n) | ||
* | ||
* 공간복잡도 : | ||
* - 이전값 저장하기 위해서 변수 2개가 쓰이므로 O(1) | ||
* | ||
*/ | ||
|
||
function climbStairs(n: number): number { | ||
if (n <= 2) return n; | ||
|
||
let prevPrevSteps = 1; | ||
let prevSteps = 2; | ||
|
||
for (let i = 3; i <= n; i++) { | ||
const currentSteps = prevPrevSteps + prevSteps; | ||
prevPrevSteps = prevSteps; | ||
prevSteps = currentSteps; | ||
} | ||
|
||
return prevSteps; | ||
} | ||
68 changes: 68 additions & 0 deletions
68
construct-binary-tree-from-preorder-and-inorder-traversal/mmyeon.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
export class TreeNode { | ||
val: number; | ||
left: TreeNode | null; | ||
right: TreeNode | null; | ||
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { | ||
this.val = val === undefined ? 0 : val; | ||
this.left = left === undefined ? null : left; | ||
this.right = right === undefined ? null : right; | ||
} | ||
} | ||
|
||
/** | ||
* | ||
* 접근 방법 | ||
* - preorder는 root -> left -> right 순서로 진행되니까 첫 번째 요소가 root노드 값인 점을 이용 | ||
* - preorder에서 root 노드 값 파악 | ||
* - inorder(left -> root -> right)에서 head 노드 기준으로 왼쪽 서브 트리, 오른쪽 하위 서브 나누기 | ||
* - inorder의 왼쪽 트리 노드 개수 활용해서 preorder도 왼쪽, 오른쪽 나누기 | ||
* - 재귀 함수를 통해서 위 과정 반복하기 | ||
* - 재귀 함수 기저 조건으로 빈 배열이 들어오는 경우 null처리 | ||
* | ||
* 시간복잡도 : O(n) | ||
* - forEach문으로 map에 값 초기화하니까 O(n) | ||
* - dfs가 각 노드 방문해서 노드 개수 n만큼 호출하니까 O(n) | ||
* | ||
* 공간복잡도 : O(n) | ||
* - indexMap - n이 노드의 개수일 때 map에 노드의 인덱스 모두 저장하니까 O(n) | ||
* - 최악의 경우 한쪽으로 치우친 트리의 경우 재귀 호출 O(n) | ||
* | ||
*/ | ||
function buildTree(preorder: number[], inorder: number[]): TreeNode | null { | ||
// index 미리 map에 저장해두기 | ||
const indexMap = new Map<number, number>(); | ||
inorder.forEach((number, index) => indexMap.set(number, index)); | ||
|
||
// preorder index, inorder range를 전달하기 | ||
const dfs = ( | ||
preorderIndex: number, | ||
inorderStartIndex: number, | ||
inorderEndIndex: number | ||
): TreeNode | null => { | ||
// 기저 조건 | ||
if ( | ||
!(preorderIndex < preorder.length && inorderStartIndex <= inorderEndIndex) | ||
) | ||
return null; | ||
|
||
const rootValue = preorder[preorderIndex]; | ||
const inorderRootIndex = indexMap.get(rootValue) as number; | ||
|
||
// 왼쪽 하위 트리 범위 = inorder 배열의 start부터 root인덱스 이전까지 | ||
const left = dfs( | ||
preorderIndex + 1, | ||
inorderStartIndex, | ||
inorderRootIndex - 1 | ||
); | ||
// 오른쪽 하위 트리 범위 = root인덱스 다음부터 끝까지 | ||
const right = dfs( | ||
preorderIndex + 1 + (inorderRootIndex - inorderStartIndex), | ||
inorderRootIndex + 1, | ||
inorderEndIndex | ||
); | ||
|
||
return new TreeNode(rootValue, left, right); | ||
}; | ||
|
||
return dfs(0, 0, inorder.length - 1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* | ||
* 접근 방법 : | ||
* - 두 문자 정렬하면 O(nlogn)이니까 정렬 대신 객체 사용해서 빈도수 체크하는 방법으로 선택 | ||
* - 첫 번쨰 문자열 순회해서 객체에 문자별 빈도수 저장하고, 두 번째 문자열 순회하면서 빈도수 감소시키기 | ||
* - 모든 문자의 빈도수가 0이 되어야 anagram이라는 의미니까, 0인 경우 true 리턴 | ||
* | ||
* 시간복잡도 : | ||
* - 두 객체 for문으로 순회해야 하니까 O(n) | ||
* | ||
* 공간복잡도 : | ||
* - 문자 빈도수를 객체의 크기는 입력 문자열 길이에 비레하니까 O(n) | ||
* | ||
*/ | ||
|
||
function isAnagram(s: string, t: string): boolean { | ||
// 두 문자열 길이가 다른 경우는 anagram이 될 수 없으니까 초기 리턴 처리 | ||
if (s.length !== t.length) return false; | ||
|
||
const charCount: Record<string, number> = {}; | ||
|
||
for (const letter of s) { | ||
charCount[letter] = (charCount[letter] ?? 0) + 1; | ||
} | ||
|
||
for (const letter of t) { | ||
if (!charCount[letter]) return false; | ||
charCount[letter]--; | ||
} | ||
|
||
for (const count in charCount) { | ||
if (charCount[count] !== 0) return false; | ||
} | ||
|
||
return true; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeScript는 잘 몰라서 제 파이썬 코드와 비교해봤는데, @mmyeon 님 코드를 통해서 중간 결과를 dp 배열에 모두 저장하는 대신 두 개의 변수만 사용하면 공간복잡도를 더 최적화할 수 있다는 걸 배웠어요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KwonNayeon
안녕하세요! 귀중한 시간 내어서 코드 리뷰 해주셔서 정말 감사합니다 👍
저도 다른 분들 풀이 참고해서 작성해보았는데 도움이 되셨다니 뿌듯합니다.
다시 한번 감사드립니다 :)