-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #820 from mmyeon/main
[mallayon] Week 4
- Loading branch information
Showing
5 changed files
with
206 additions
and
0 deletions.
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,27 @@ | ||
/** | ||
* | ||
* 접근 방법 : | ||
* - 동전 최소 개수 구하는 문제니까 DP로 풀기 | ||
* - 코인마다 순회하면서 동전 개수 최소값 구하기 | ||
* - 기존값과 코인을 뺀 값 + 1 중 작은 값으로 업데이트 | ||
* | ||
* 시간복잡도 : O(n * m) | ||
* - 코인 개수 n만큼 순회 | ||
* - 각 코인마다 amount 값(m) 될 때까지 순회 | ||
* | ||
* 공간복잡도 : O(m) | ||
* - amount 만큼 dp 배열 생성 | ||
* | ||
*/ | ||
function coinChange(coins: number[], amount: number): number { | ||
const dp = Array(amount + 1).fill(Number.MAX_VALUE); | ||
dp[0] = 0; | ||
|
||
for (const coin of coins) { | ||
for (let i = coin; i <= amount; i++) { | ||
dp[i] = Math.min(dp[i], dp[i - coin] + 1); | ||
} | ||
} | ||
|
||
return dp[amount] === Number.MAX_VALUE ? -1 : dp[amount]; | ||
} |
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,46 @@ | ||
class ListNode { | ||
val: number; | ||
next: ListNode | null; | ||
constructor(val?: number, next?: ListNode | null) { | ||
this.val = val === undefined ? 0 : val; | ||
this.next = next === undefined ? null : next; | ||
} | ||
} | ||
|
||
/** | ||
* | ||
* 접근 방법 : | ||
* - 2개의 정렬된 링크드 리스트가 주어지니까 각 리스트 값 비교하면서 작은 값을 새로운 링크드 리스트에 추가 | ||
* - 링크드 리스트 head에 접근해야하니까 더미노드와 포인터 변수 분리해서 사용 | ||
* - 포인터 변수 사용해서 노드 연결하기 | ||
* - 두 링크드 리스트가 있는 동안 반복하고, 한 쪽이 끝나면 나머지 노드를 그대로 새로운 링크드 리스트에 추가 | ||
* | ||
* 시간복잡도 : O(n+k) | ||
* - n은 list1 길이, k는 list2 길이 => 두 리스트 모두 반복하니까 O(n+k) | ||
* | ||
* 공간복잡도 : O(1) | ||
* - 기존 노드 연결해서 재사용하니까 O(1) | ||
*/ | ||
|
||
function mergeTwoLists( | ||
list1: ListNode | null, | ||
list2: ListNode | null | ||
): ListNode | null { | ||
const dummyNode = new ListNode(); | ||
let current = dummyNode; | ||
|
||
while (list1 !== null && list2 !== null) { | ||
if (list1.val <= list2.val) { | ||
current.next = list1; | ||
list1 = list1.next; | ||
current = current.next; | ||
} else { | ||
current.next = list2; | ||
list2 = list2.next; | ||
current = current.next; | ||
} | ||
} | ||
current.next = list1 !== null ? list1 : list2; | ||
|
||
return dummyNode.next; | ||
} |
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 @@ | ||
/** | ||
* | ||
* 접근 방법 : | ||
* - 연속되는 숫자 중 빠진 숫자 찾는 거니까 배열 인덱스를 활용하자. | ||
* - 배열 요소 순회하면서 map에 요소를 키로 넣고, nums 길이만큼 순회하면서 map에 값 있는지 체크 | ||
* - 없으면 해당 인덱스 리턴하고, 순회 끝나면 nums 길이 리턴 | ||
* | ||
* 시간복잡도 : O(n) | ||
* - nums 길이만큼 map에 요소 넣고, map에 요소 있는지 체크하니까 O(n) | ||
* | ||
* 공간복잡도 : O(n) | ||
* - map에 nums 길이만큼 저장하니까 O(n) | ||
*/ | ||
|
||
function missingNumber(nums: number[]): number { | ||
const set = new Set(nums); | ||
|
||
for (let i = 0; i < nums.length; i++) { | ||
if (!set.has(i)) return i; | ||
} | ||
|
||
return nums.length; | ||
} | ||
|
||
// 공간복잡도 O(1) 개선 방법 | ||
// - 0부터 n까지의 합 구하고, 실제 nums 요소 값 빼서 빠진 숫자 구함 | ||
function missingNumber(nums: number[]): number { | ||
let sum = 0; | ||
|
||
for (let i = 0; i <= nums.length; i++) { | ||
sum += i; | ||
if (i < nums.length) sum -= nums[i]; | ||
} | ||
|
||
return sum; | ||
} |
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,37 @@ | ||
/** | ||
* | ||
* 접근 방법 : | ||
* - 각 문자열에서 회문 조건 충족하는 경우 중심을 기준으로 확장해나가기 위해 투 포인터 사용 | ||
* - 문자가 같고 범위 내에 있는 경우 확장해나가면서 횟수 업데이트 | ||
* - 홀수 회문과 다르게 짝수 회문은 중심을 2문자에서 시작되어야 하니까 인덱스 별도 처리 | ||
* | ||
* 시간복잡도 : O(n^2) | ||
* - 문자열 길이가 n일 때, for문에서 각 문자마다 최대 문자열 길이까지 비교하니까 O(n^2) | ||
* | ||
* 공간복잡도 : O(1) | ||
* | ||
*/ | ||
|
||
function countPalindromes(s: string, left: number, right: number): number { | ||
let count = 0; | ||
|
||
while (0 <= left && right < s.length && s[left] === s[right]) { | ||
count++; | ||
left--; | ||
right++; | ||
} | ||
|
||
return count; | ||
} | ||
|
||
function countSubstrings(s: string): number { | ||
let count = 0; | ||
|
||
for (let i = 0; i < s.length; i++) { | ||
// 홀수 회문 카운트 | ||
count += countPalindromes(s, i, i); | ||
// 짝수 회문 카운트 | ||
count += countPalindromes(s, i, i + 1); | ||
} | ||
return count; | ||
} |
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 @@ | ||
/** | ||
* | ||
* 접근 방법 : | ||
* 1. 행렬 순회하며 word와 첫 번째 문자가 같은지 체크 | ||
* 2. 같으면 DFS(재귀)로 네 방향(상하좌우)을 탐색한다. | ||
* - 현재 위치가 유효한지 체크 = 범위 안인가, 문자가 같은가 | ||
* - 단어 다 찾아서 index가 단어 길이와 같은지 체크 | ||
* 3. 이미 방문한 노드 제외하기 위해서 네 방향 체크하기 전에 방문 여부 표시하기 | ||
* 4. 4방향으로 문자 체크하기 | ||
* 5. 재귀 호출하는 동안 찾지 못한 경우 방문 여부 초기화하기 (backtracking) | ||
* | ||
* 시간복잡도 : O(N * M * 4^L) | ||
* - L는 word의 길이, word 길이만큼 네 방향 체크하니까 O(4^L) | ||
* 공간복잡도 : O(L) | ||
* | ||
* - L는 word의 길이, 찾으려는 단어 길이만큼 재귀 호출되니까 O(L) | ||
* | ||
*/ | ||
|
||
function exist(board: string[][], word: string): boolean { | ||
const rows = board.length; | ||
const cols = board[0].length; | ||
|
||
const dfs = (x: number, y: number, index: number): boolean => { | ||
// 종료조건 : 문자를 다 찾은 경우 | ||
if (index === word.length) return true; | ||
|
||
// 범위를 벗어나거나 이미 방문했거나 문자가 다른 경우 | ||
if (x < 0 || y < 0 || x >= rows || y >= cols || board[x][y] !== word[index]) | ||
return false; | ||
|
||
// 방문 표시 | ||
const temp = board[x][y]; | ||
board[x][y] = "#"; | ||
|
||
// 4 방향 | ||
const directions = [ | ||
[1, 0], | ||
[0, 1], | ||
[-1, 0], | ||
[0, -1], | ||
]; | ||
|
||
for (const [dx, dy] of directions) { | ||
if (dfs(x + dx, y + dy, index + 1)) return true; | ||
} | ||
|
||
// 백트래킹 | ||
board[x][y] = temp; | ||
return false; | ||
}; | ||
|
||
for (let i = 0; i < rows; i++) { | ||
for (let j = 0; j < cols; j++) { | ||
if (word[0] === board[i][j] && dfs(i, j, 0)) return true; | ||
} | ||
} | ||
|
||
return false; | ||
} |