From 315d3654737e71dc2de7e4d8bf966cd359fa0ce2 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sun, 20 Apr 2025 14:55:30 +0900 Subject: [PATCH 1/6] feat: add week04 problems --- coin-change/shinsj4653.py | 15 +++++++++++++++ .../shinsj4653.py | 15 +++++++++++++++ maximum-depth-of-binary-tree/shinsj4653.py | 15 +++++++++++++++ merge-two-sorted-lists/shinsj4653.py | 15 +++++++++++++++ word-search/shinsj4653.py | 15 +++++++++++++++ 5 files changed, 75 insertions(+) create mode 100644 coin-change/shinsj4653.py create mode 100644 find-minimum-in-rotated-sorted-array/shinsj4653.py create mode 100644 maximum-depth-of-binary-tree/shinsj4653.py create mode 100644 merge-two-sorted-lists/shinsj4653.py create mode 100644 word-search/shinsj4653.py diff --git a/coin-change/shinsj4653.py b/coin-change/shinsj4653.py new file mode 100644 index 000000000..f2dd9f373 --- /dev/null +++ b/coin-change/shinsj4653.py @@ -0,0 +1,15 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" + + diff --git a/find-minimum-in-rotated-sorted-array/shinsj4653.py b/find-minimum-in-rotated-sorted-array/shinsj4653.py new file mode 100644 index 000000000..f2dd9f373 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/shinsj4653.py @@ -0,0 +1,15 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" + + diff --git a/maximum-depth-of-binary-tree/shinsj4653.py b/maximum-depth-of-binary-tree/shinsj4653.py new file mode 100644 index 000000000..f2dd9f373 --- /dev/null +++ b/maximum-depth-of-binary-tree/shinsj4653.py @@ -0,0 +1,15 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" + + diff --git a/merge-two-sorted-lists/shinsj4653.py b/merge-two-sorted-lists/shinsj4653.py new file mode 100644 index 000000000..f2dd9f373 --- /dev/null +++ b/merge-two-sorted-lists/shinsj4653.py @@ -0,0 +1,15 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" + + diff --git a/word-search/shinsj4653.py b/word-search/shinsj4653.py new file mode 100644 index 000000000..f2dd9f373 --- /dev/null +++ b/word-search/shinsj4653.py @@ -0,0 +1,15 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" + + From 6d98663b51f49179ad792d9256e235e1bf101619 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Mon, 21 Apr 2025 22:44:56 +0900 Subject: [PATCH 2/6] feat: add word-search solution --- word-search/shinsj4653.py | 141 +++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 3 deletions(-) diff --git a/word-search/shinsj4653.py b/word-search/shinsj4653.py index f2dd9f373..ceccff14c 100644 --- a/word-search/shinsj4653.py +++ b/word-search/shinsj4653.py @@ -1,15 +1,150 @@ """ [문제풀이] # Inputs - +- board: m*n grid of characters +- word: str # Outputs - +- word 가 grid 안에 있으면 true, 아니면 false # Constraints +- 탐색: 상하좌우 +- m == board.length +- n = board[i].length +- 1 <= m, n <= 6 +- 1 <= word.length <= 15 +- board, word => 무조건 대소문자로 구성 # Ideas +1. 퍼지면서 탐색 -> bfs? +q = cur.append(i, j, "") +q.pop() 해서 +if 현재 w 가 word랑 같다면 그 즉시 bfs stop하고 return True +만약 bfs 끝까지 했는데도 안나오면 return False -[회고] +bfs: q에 다음 원소 넣을 때 현재 값에 이어붙인문자가 w랑 어떤식으로 비교해야 맞는 조건절이 되는걸까? +=> cur_w의 len 값을 i로 사용하려했지만 w가 더 짧으면 idxError 뜰까봐 보류 +=> 메모리 초과 오류 뜸.. +=> 아..같은 자리를 방문하면 안됨!! 즉, 원복이 필요함! +-> 백트래킹으로 풀이 change + +2. dfs로도 꼭 풀어보기! +백트래킹 복습 용으로 굿 + +board안의 숫자는 오직 대소문자 -> isalpha() 로 체킹 가능 +=> 방문하면 0으로 바꾸기 + +풀기는 풀었지만..7090ms : Beats 7.34% + +Follow up : Could you use search pruning to make your solution faster with a larger board +가지치기 기법 어떻게 도입할까?? +=> cur_idx 하나 둬서, AB.. ABC -> 진행 도중, 하나라도 word랑 다르면 바로 그 경로 컷 +=> 그래도 4587ms.. Beats 41.00% +=> 먼가 더 정석 성능 개선이 필요 + +해설 참고 +=> word_idx를 이용, any문을 이용한 리팩토링 +=> 해설 풀이 : 4385ms +[회고] +idx를 이용한 가지치기 방법 잘 알아두자 """ +# from collections import deque +# class Solution: +# def exist(board, word): +# +# q = deque([]) +# n, m = len(board), len(board[0]) +# +# q.append((0, 0, board[0][0])) +# +# dy = [-1, 0, 1, 0] +# dx = [0, 1, 0, -1] +# +# while q: +# cur_y, cur_x, cur_w = q.popleft() +# +# if cur_w == word: +# return True +# +# for i in range(3): +# ny = cur_y + dy[i] +# nx = cur_x + dx[i] +# +# if 0 <= ny < n and 0 <= nx < m: +# q.append((ny, nx, cur_w + board[ny][nx])) +# +# return False +# +# exist([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCDE") + + +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + + n, m = len(board), len(board[0]) + + dy = [-1, 0, 1, 0] + dx = [0, 1, 0, -1] + + v = [[False for _ in range(m)] for _ in range(n)] + + def dfs(y, x, w): + #print('y, x : ', y, x) + #print('w: ', w) + if w == word: + return True + + if len(w) >= len(word): + return False + + for k in range(4): + ny = y + dy[k] + nx = x + dx[k] + + if 0 <= ny < n and 0 <= nx < m and not v[ny][nx]: + v[ny][nx] = True + if dfs(ny, nx, w + board[ny][nx]): + return True + v[ny][nx] = False + + for i in range(n): + for j in range(m): + if not v[i][j] and board[i][j] == word[0]: + v[i][j] = True + if dfs(i, j, board[i][j]): + return True + v[i][j] = False + + return False + +# 해설 +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + + n, m = len(board), len(board[0]) + + dy = [-1, 0, 1, 0] + dx = [0, 1, 0, -1] + + def dfs(y, x, idx): + if idx == len(word): + return True + + if not (0 <= y < n and 0 <= x < m): + return False + + if board[y][x] != word[idx]: + return False + + temp = board[y][x] + board[y][x] = "" + + for i in range(4): + if dfs(y + dy[i], x + dx[i], idx + 1): + return True + + board[y][x] = temp + return False + + return any(dfs(i, j, 0) for i in range(n) for j in range(m)) From acf37c0cff16e645622b1279f2c98283c7787800 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 26 Apr 2025 20:43:03 +0900 Subject: [PATCH 3/6] feat: add coin-change solution --- coin-change/shinsj4653.py | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/coin-change/shinsj4653.py b/coin-change/shinsj4653.py index f2dd9f373..246706c18 100644 --- a/coin-change/shinsj4653.py +++ b/coin-change/shinsj4653.py @@ -1,15 +1,45 @@ """ [문제풀이] # Inputs - +- 정수 배열 coins +- 총 돈의 값 amount # Outputs - +- amount 를 채울 수 있는 동전의 가장 적은 수 +- 만약 만들 수 없다면 -1 return # Constraints - +- 1 <= coins.length <= 12 +- 1 <= coins[i] <= 2^31 - 1 +- 0 <= amount <= 10^4 # Ideas +- 우선 이전 풀이 본 거 연습해보기 +- DP 탑다운 방식으로! 이 문제 풀이를 내가 100% 이해하고 있는게 맞는지 손으로 도식화 해보기로함 -[회고] +[회고] +재귀랑 dp는 다양한 유형을 많이 풀어보는 수 밖에.. """ +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + memo = {} + + def dp(amount): + + if amount == 0: + return 0 + + retList = [] + for coin in coins: + if amount - coin >= 0: + if amount - coin not in memo: + memo[amount - coin] = dp(amount - coin) + + if memo[amount - coin] != -1: + retList.append(memo[amount - coin]) + + return min(retList) + 1 if retList else -1 + + return dp(amount) + + From caca32904a8b88c68160a5486bb20052c139cd9f Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 26 Apr 2025 23:17:56 +0900 Subject: [PATCH 4/6] feat: add merge-two-sorted-lists solution --- merge-two-sorted-lists/shinsj4653.py | 51 ++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/merge-two-sorted-lists/shinsj4653.py b/merge-two-sorted-lists/shinsj4653.py index f2dd9f373..2b7a9f575 100644 --- a/merge-two-sorted-lists/shinsj4653.py +++ b/merge-two-sorted-lists/shinsj4653.py @@ -1,15 +1,60 @@ """ [문제풀이] # Inputs - +- two sorted linked lists # Outputs - +- 두 링크드 리스트를 합쳐서 하나의 정렬된 (오름차순) 리스트 반환 # Constraints - +- The number of nodes in both lists is in the range [0, 50]. +- -100 <= Node.val <= 100 +- Both list1 and list2 are sorted in non-decreasing order. # Ideas +두 링크드 리스트는 모두 오름차순으로 정렬되어 있음 +-> ListNode는 val, next 로 되어있음 + +우선 두 리스트 이어붙이고, +먼가 리스트 정렬 알고리즘 써야할듯? +리스트라서, 두 노드를 바꾸는 swap() 함수 쓰면서, +왼쪽보다 오른쪽이 작으면 바꾸는 식으로 하면 될듯? + +즉, 붙어있는 두 노드 비교하면서 쭉 돌기 +하지만 인덱스가 없어서 어떻게 순회할지? +-> point라는 기준을 둬서 이 point를 기준으로 prev, next를 만들어서 순회 +-> 근데 prev, next만으로는 swap이 어려워서 2개가 아닌 3개를 둬야할 것 같은데, +구현 방법이 떠오르지 않아서 해설 참고 + +해설 참고 +- 기존 리스트 변경이 아닌, 아예 새로운 리스트를 재창조 하는 방식으로! + [회고] +기존 리스트를 swap하려고 하다 보니, 어렵게 생각하게됨.. """ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + + retList = ListNode(None) + head = retList + + while list1 and list2: + if list1.val < list2.val: + head.next = list1 + list1 = list1.next + + else: + head.next = list2 + list2 = list2.next + + head = head.next + + head.next = list1 or list2 + return retList.next + \ No newline at end of file From 94686144d3ad089a0e9e5d2c65718f896ac2527d Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 26 Apr 2025 23:34:08 +0900 Subject: [PATCH 5/6] feat: add maximum-depth-of-binary-tree sol --- maximum-depth-of-binary-tree/shinsj4653.py | 47 ++++++++++++++++++++-- merge-two-sorted-lists/shinsj4653.py | 2 +- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/maximum-depth-of-binary-tree/shinsj4653.py b/maximum-depth-of-binary-tree/shinsj4653.py index f2dd9f373..7d09b54ac 100644 --- a/maximum-depth-of-binary-tree/shinsj4653.py +++ b/maximum-depth-of-binary-tree/shinsj4653.py @@ -1,15 +1,56 @@ """ [문제풀이] # Inputs - +- 이진 트리의 root # Outputs - +- 가장 최고 깊이 # Constraints - +The number of nodes in the tree is in the range [0, 104]. +-100 <= Node.val <= 100 # Ideas +dfs, 즉 재귀 돌면서 +depth 를 max로 업데이트 하면 될 것 같은 느낌? [회고] +내 풀이는 정답 +해설 방법도 궁금하여 참고 +-> TC, SC도 파악하는 연습! + +TC: o(n) +SC: o(n) """ +# 내 풀이 +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + def dfs(node, depth): + if node is None: + return depth - 1 + + return max(dfs(node.left, depth + 1), dfs(node.right, depth + 1)) + + return dfs(root, 1) +# 해설 +# bfs 풀이도 존재 +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + max_depth = 0 + stack = [(root, 1)] + while stack: + node, depth = stack.pop() + max_depth = max(depth, max_depth) + if node.left: + stack.append((node.left, depth + 1)) + if node.right: + stack.append((node.right, depth + 1)) + return max_depth diff --git a/merge-two-sorted-lists/shinsj4653.py b/merge-two-sorted-lists/shinsj4653.py index 2b7a9f575..c85a4ed69 100644 --- a/merge-two-sorted-lists/shinsj4653.py +++ b/merge-two-sorted-lists/shinsj4653.py @@ -57,4 +57,4 @@ def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> head.next = list1 or list2 return retList.next - \ No newline at end of file + From afe0d4a35998401a585d551ee3b4a022fd37c7f9 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sun, 27 Apr 2025 00:24:07 +0900 Subject: [PATCH 6/6] feat: add find-minimum-in-rotated-sorted-array sol --- .../shinsj4653.py | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/find-minimum-in-rotated-sorted-array/shinsj4653.py b/find-minimum-in-rotated-sorted-array/shinsj4653.py index f2dd9f373..ff858b4a9 100644 --- a/find-minimum-in-rotated-sorted-array/shinsj4653.py +++ b/find-minimum-in-rotated-sorted-array/shinsj4653.py @@ -1,15 +1,83 @@ """ [문제풀이] # Inputs - +- sorted rotated array : nums +- nums안의 요소는 unique # Outputs - +- 배열의 가장 작은 값 Return # Constraints - +- O(logN) 시간대로 풀어야함 +- n == nums.length +- 1 <= n <= 5000 +- -5000 <= nums[i] <= 5000 +- All the integers of nums are unique. +- nums is sorted and rotated between 1 and n times. # Ideas +그냥 정렬은 O(NlogN) 이어서 불가능 +rotate : 맨 끝의 요소가 맨 처음으로 옴 +이진탐색이 O(logN) 이긴한데..->하지만, 이진탐색은 정렬된 배열에서만 사용가능 +그리고, 이 문제에선 아닌 것 같다 + +끝의 원소를 빼서 stack에 append -> 모두 o(1) + +회전되어 있는 배열의 특성을 활용하여 +-> 끝의 원소 빼고, 그걸 stack 에 넣기 +-> 그리고 stack의 맨 끝 원소보다 nums의 끝 원소가 더 클때 +stack[-1] 이 정답 +-> 근데 이건 o(n) 아닌가?? + +우선 내 풀이 정답 +해설 참고 +-> 내 풀이는 O(n) 이다.. O(logN) 풀이가 필요 +이분탐색 응용문제이다 [회고] """ +# 내 풀이 +from collections import deque + + +class Solution: + def findMin(self, nums: List[int]) -> int: + + if len(nums) == 1: + return nums[0] + + nums = deque(nums) + + st = [] + ret = 0 + + while nums: + num = nums.pop() + + if not nums: + ret = num + break + + if num < nums[-1]: + ret = num + break + + return ret + +# 해설 +class Solution: + def findMin(self, nums: List[int]) -> int: + + left, right = 1, len(nums) - 1 + + while left <= right: + mid = (left + right) // 2 + if nums[mid - 1] > nums[mid]: + return nums[mid] + if nums[0] < nums[mid]: + left = mid + 1 + else: + right = mid - 1 + + return nums[0] +