-
-
Notifications
You must be signed in to change notification settings - Fork 245
[hi-rachel] WEEK 02 solutions #1768
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
Changes from all commits
1c489a3
82cfd90
ec12b17
dfdc227
cbe8951
8e8234a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
""" | ||
https://leetcode.com/problems/climbing-stairs/description/ | ||
|
||
한 번에 1계단 혹은 2계단 오를 수 있음 | ||
1: 1 | ||
2: 2 | ||
3: 1 + 1 + 1, 1 + 2, 2 + 1 => 3 | ||
4: 1 + 1 + 1 + 1, 1 + 1 + 2, 2 + 1 + 1, 1 + 2 + 1, 2 + 2 => 5 | ||
5: 1 + 1 + 1 + 1 + 1, | ||
1 + 1 + 1 + 2, | ||
1 + 1 + 2 + 1 + 1, | ||
1 + 2 + 1 + 1, | ||
2 + 1 + 1 + 1, | ||
2 + 2 + 1, | ||
2 + 1 + 2, | ||
1 + 2 + 2, | ||
=> 8 | ||
|
||
steps[n] = steps[n - 1] + steps[n - 2] | ||
|
||
TC: O(n) | ||
SC: O(n) | ||
""" | ||
|
||
class Solution: | ||
def climbStairs(self, n: int) -> int: | ||
if n == 1: | ||
return 1 | ||
elif n == 2: | ||
return 2 | ||
steps = [0] * n | ||
steps[0] = 1 | ||
steps[1] = 2 | ||
for i in range(2, n): | ||
steps[i] = steps[i - 2] + steps[i - 1] | ||
return steps[n - 1] | ||
|
||
""" | ||
변수 2개로 최적화 | ||
공간 복잡도 O(1) 개선 풀이 | ||
""" | ||
class Solution: | ||
def climbStairs(self, n: int) -> int: | ||
if n == 1: | ||
return 1 | ||
elif n == 2: | ||
return 2 | ||
|
||
prev1 = 1 | ||
prev2 = 2 | ||
|
||
for i in range(2, n): | ||
prev1, prev2 = prev2, prev1 + prev2 | ||
return prev2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
""" | ||
https://leetcode.com/problems/product-of-array-except-self/description/ | ||
|
||
문제: 정수 배열 nums가 주어졌을 때, 각 원소를 제외한 나머지 원소들의 곱을 반환하세요. | ||
단, 나누기 연산을 사용하지 말고 O(n) 시간 복잡도로 해결하세요. | ||
|
||
핵심 아이디어: | ||
각 원소를 기준으로: | ||
- 왼쪽에 있는 원소들의 곱 | ||
- 오른쪽에 있는 원소들의 곱 | ||
을 각각 곱해주면, 자기 자신을 제외한 전체 곱이 된다. | ||
|
||
예시: [1, 2, 3, 4] | ||
- 인덱스 0: 왼쪽(없음) × 오른쪽(2×3×4) = 24 | ||
- 인덱스 1: 왼쪽(1) × 오른쪽(3×4) = 12 | ||
- 인덱스 2: 왼쪽(1×2) × 오른쪽(4) = 8 | ||
- 인덱스 3: 왼쪽(1×2×3) × 오른쪽(없음) = 6 | ||
|
||
TC: O(n) - 배열을 두 번 순회 | ||
SC: O(1) - 결과 배열을 제외한 추가 공간 사용하지 않음 | ||
""" | ||
|
||
from typing import List | ||
|
||
class Solution: | ||
def productExceptSelf(self, nums: List[int]) -> List[int]: | ||
n = len(nums) | ||
result = [1] * n # 결과 배열 초기화 | ||
|
||
# 1단계: 왼쪽에서 오른쪽으로 순회하며 왼쪽 원소들의 곱 계산 | ||
left_product = 1 | ||
for i in range(n): | ||
result[i] = left_product # 현재 위치에 왼쪽 곱 저장 | ||
left_product *= nums[i] # 다음을 위해 현재 원소 곱하기 | ||
|
||
# 2단계: 오른쪽에서 왼쪽으로 순회하며 오른쪽 원소들의 곱 계산 | ||
right_product = 1 | ||
for i in range(n - 1, -1, -1): | ||
result[i] *= right_product # 기존 왼쪽 곱에 오른쪽 곱 곱하기 | ||
right_product *= nums[i] # 다음을 위해 현재 원소 곱하기 | ||
|
||
return result |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드를 구조화하여 세가지 방법을 모두 제공한 것이 매우 좋습니다 :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @printjin-gmailcom 이번에 재수 2번째 도전이라 여러 풀이로 도전했습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 안그래도 꽤나 익숙한 아이디이긴했어요 ㅎㅎ 코드가 다 깔끔하고 좋아서 많이 배워갑니다다. 5기 화이팅 :) |
||
https://leetcode.com/problems/valid-anagram/description/ | ||
두 문자열이 애너그램인지 확인하는 함수를 작성하세요. | ||
애너그램이란 두 문자열이 중복된 알파벳을 같은 개수만큼 포함하고 있는 것을 의미합니다. | ||
TC: O(n) | ||
SC: O(k), k = 알파벳 개수 | ||
""" | ||
|
||
from collections import defaultdict | ||
|
||
class Solution: | ||
def isAnagram(self, s: str, t: str) -> bool: | ||
def makeMap(s: str): | ||
str_map = defaultdict(int) | ||
for char in s: | ||
str_map[char] += 1 | ||
return str_map | ||
|
||
return makeMap(s) == makeMap(t) | ||
|
||
|
||
""" | ||
정렬 풀이 | ||
TC: O(nlogn) | ||
SC: O(1) | ||
""" | ||
def isAnagram(s: str, t: str) -> bool: | ||
return sorted(s) == sorted(t) | ||
|
||
""" | ||
Counter 사용 풀이 | ||
TC: O(n) | ||
SC: O(k) | ||
""" | ||
from collections import Counter | ||
|
||
def isAnagram(s: str, t: str) -> bool: | ||
return Counter(s) == Counter(t) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,73 @@ | ||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드를 구조화하여 두 방법을 모두 제공한 것이 매우 좋습니다 :) |
||
모든 왼쪽 서브트리는 현재 노드보다 작아야 하고, | ||
모든 오른쪽 서브트리는 현재 노드보다 커야 한다. | ||
이걸 위해서 범위(min/max)를 재귀로 내려보내야 한다. | ||
TC: O(n), 모든 노드 1번씩 탐색 | ||
SC: O(h), 재귀 호출 스택, h는 트리 높이 | ||
""" | ||
|
||
from typing import Optional | ||
# 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 isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
def validate(node, low, high): | ||
if not node: | ||
return True # 비어있는 노드는 BST | ||
# 현재 노드가 범위 밖이면 BST 조건 위배 | ||
if not (low < node.val < high): | ||
return False | ||
# 왼쪽은 최대값을 현재 노드보다 작게 제한 | ||
# 오른쪽은 최소값을 현재 노드보다 크게 제한 | ||
return (validate(node.left, low, node.val) and | ||
validate(node.right, node.val, high)) | ||
|
||
return validate(root, float('-inf'), float('inf')) | ||
|
||
|
||
""" | ||
스택 풀이 | ||
- BST에서 중위 순회하면 항상 오름차순이어야 한다는 성질을 이용한 방법 | ||
- 중위 순회: 왼쪽 → 현재 노드 → 오른쪽 | ||
- BST는 중위 순회 시 값이 항상 증가해야 하므로, (오름차순) | ||
이전 노드(prev)보다 현재 노드 값이 작거나 같으면 잘못된 BST | ||
TC: O(n), 모든 노드 1번씩 탐색 | ||
SC: O(h), 최대 스택 깊이 = 트리 높이 | ||
""" | ||
|
||
class Solution: | ||
def isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
stack = [] | ||
prev = None # 이전 중위 순회 값 | ||
|
||
while stack or root: | ||
# 왼쪽 끝까지 탐색 | ||
while root: | ||
stack.append(root) | ||
root = root.left | ||
|
||
root = stack.pop() | ||
|
||
# 이전 값보다 작거나 같으면 BST 위반 | ||
if prev is not None and root.val <= prev: | ||
return False | ||
prev = root.val | ||
|
||
# 오른쪽으로 이동 | ||
root = root.right | ||
|
||
return True | ||
|
||
|
||
# O(n) time, O(n) space | ||
|
||
# Definition for a binary tree node. | ||
|
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.
range 루프에서 index를 사용하지 않기에 _ 사용 적절해보입니다.
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.
@printjin-gmailcom 아 최적화하면서 index를 사용하지 않는 부분을 놓쳤네요. 감사합니다.