Skip to content

[taurus09318976] WEEK 2 solutions #1270

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

Merged
merged 1 commit into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions 3sum/taurus09318976.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 이 문제는 1)정렬을 통해 중복을 처리, 2)투 포인터를 사용하여 효율적으로 탐색,
#3) 합이 0보다 작으면 left를 +1, 크면 right를 -1이동, 4)중복된

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() #중복된 숫자를 쉽게 처리하고, 투 포인터 기법을 사용하기 위해 배열을 정렬
result = []

#첫번째 숫자를 선택하는 루프
#마지막 두 숫자는 left와 right가 사용하므로 len(nums)-2해야 함
#예: len(nums) = 4라면, range(2)=[0,1]
for i in range(len(nums) - 2):
#첫번째 숫자가 이전과 같으면 건너뜀
if i > 0 and nums[i] == nums[i-1]:
continue

#투 포인터 설정 : left는 첫번째 숫자 다음부터, right는 배열의 끝부터 설정
left, right = i + 1, len(nums) - 1

while left < right:
total = nums[i] + nums[left] + nums[right]
#합이 0보다 작으면 left를 +1
if total < 0:
left += 1
#합이 0보다 크면 right를 -1이동
elif total > 0:
right -= 1
else:
#합이 0인 경우 처리
result.append([nums[i], nums[left], nums[right]])
#중복된 숫자 건너뛰기
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
#다음 가능한 조합을 찾기 위해 포인터를 이동
left += 1
right -= 1

return result


#시간 복잡도: O(n²)
#정렬: O(n log n)
#메인 루프: O(n²)
#공간 복잡도: O(1) (출력 배열 제외하고 추가적인 공간을 사용하지 않음)



29 changes: 29 additions & 0 deletions climbing-stairs/taurus09318976.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#이 문제는 피보나치 수열과 동일한 패턴을 가지고 있음. 피보나치 수열의 (n+1)번째 수와 같음

class Solution:
def climbStairs(self, n: int) -> int:
#n이 1이나 2인 경우는 바로 결과 반환
if n == 1:
return 1
if n == 2:
return 2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if n <= 2:
return n

조건문을 하나로 줄일 수 있을 것 같아요!

#첫 번째, 두 번째 계단의 방법 수 저장
prev, curr = 1, 2

#세 번째 계단부터 n계단까지 계산
for i in range(3, n + 1):
prev, curr = curr, prev + curr

return curr


#시간 복잡도: O(n)
#for 루프가 n-2번 실행됨(3부터 n까지)
#각 반복에서 상수 시간(1)의 연산만 수행됨
#따라서 전체 시간은 n에 비례함

#공간 복잡도: O(1)
#추가적인 배열이나 리스트를 사용하지 않음
#두 개의 변수(prev, curr)만 사용함
#입력 크기(n)가 아무리 커져도 사용하는 공간은 일정함
55 changes: 55 additions & 0 deletions product-of-array-except-self/taurus09318976.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#이 문제는 배열의 각 요소 i를 제외한 나머지 요소들의 곱을 구하는 문제임
#1)각 요소 i를 기준으로 왼쪽 숫자들의 곱과 오른쪽 숫자들의 곱을 따로 계산, 2)최종 결과는 왼쪽 곱과 오른쪽 곱의 곱

class Solution:
def productExceptSelf(self, nums: List[int]):
#입력 배열의 길이를 저장
##Example 1의 경우 : len(nums) = 4
n = len(nums)
#결과를 저장할 배열을 곱셈의 항등원인 1로 모두 초기화
#cf. 빈 집합의 곱은 1, 합은 0으로 정의됨
##answer = [1] * 4 = [1, 1, 1, 1]
answer = [1] * n

#i를 기준으로 왼쪽 숫자들의 곱을 계산
#왼쪽 곱의 초기값
left_product = 1
for i in range(n):
#현재 위치의 왼쪽 곱을 저장
##nums[0]의 왼쪽에는 아무 숫자도 없으므로,
##아무것도 없는 상태의 곱은 1임. 따라서 answer[0]=1
##answer[1]=1 / answer[2]=2 / answer[3]=6
answer[i] = left_product
#다음 위치를 위해 현재 수를 곱함
##left_product = 1 * 1 = 1 / left_product = 1 * 2 = 2
##left_product = 2 * 3 = 6 / left_product = 6 * 4 = 24
left_product *= nums[i]

##첫 번째 for문 후 answer = [1, 1, 2, 6]
#i를 기준으로 오른쪽 숫자들의 곱 계산 및 최종 결과 생성
right_product = 1
#오른쪽에서 왼쪽으로 순회
for i in range(n-1, -1, -1):
#현재 위치의 오른쪽 곱을 저장
##answer[3] = 6 * 1 = 6 / answer[2] = 2 * 1 = 2
##answer[1] = 1 * 1 = 1 / answer[1] = 1 * 1 = 1
answer[i] *= right_product
#다음 위치를 위해 현재 수를 곱함
##right_product = 1 * 4 = 4 / right_product = 4 * 3 = 12
##right_product = 12 * 2 = 24 / right_product = 24 * 1 = 24
right_product *= nums[i]


#최종 결과를 반환
##최종 answer = [24, 12, 8, 6]
return answer

#시간 복잡도: O(n)
##두 번의 선형 순회만 수행하며, 각 순회는 O(n) 시간이 소요
#공간 복잡도: O(1)
##추가적인 공간을 사용하지 않음
##단, 출력 배열은 문제의 요구사항이므로 제외




31 changes: 31 additions & 0 deletions valid-anagram/taurus09318976.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파이썬에서 Counter() 이라는 함수를 아실 수도 있지만 혹시나 해서 알려드립니다!

Copy link
Contributor Author

@taurus09318976 taurus09318976 Apr 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호..그 방법이 제일 간단하겠네요..

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#이 문제를 해결하기 위해선 1)두 문자열의 길이가 같은지 확인(길이가 다르면 아나그램이 될 수 없음), 2)char_count딕셔너리를 사용하여 첫번째 문자열의 문자별 개수를 확인, 3)두번째 문자열을 순회하면서 각 문자의 개수를 하나씩 감소시킴, 4)만약 두번째 문자열에 첫번째 문자열에 없는 문자가 있거나, 어떤 문자의 개수가 음수가 되면(첫번째 문자열에 있는 문자가 두번째 문자열에 없다는 의미) 아나그램이 아님
class Solution:
def isAnagram(self, s: str, t: str):
# 두 문자열의 길이가 다르면 아나그램이 될 수 없음
if len(s) != len(t):
return False

# 각 문자의 개수를 저장할 빈 딕셔너리
char_count = {}

# 첫 번째 문자열의 각 문자를 순회
for i in s:
#해당 문자가 없으면 0, 있으면 현재값 i를 반환하고, 각 문자의 개수 1을 더함
char_count[i] = char_count.get(i, 0) + 1

# 두 번째 문자열의 문자별 개수만큼 char_count딕셔너리에서 빼기
for i in t:
#첫번째 문자열에 없는 문자가 있는 경우
if i not in char_count:
return False

char_count[i] -= 1
#char_count가 음수이므로 첫번째 문자열에 있는 문자가 두번째 문자열에 없다는 의미
if char_count[i] < 0:
return False

return True


#시간 복잡도: O(n), n= 문자열의 길이
#공간 복잡도: O(1), 입력 크기(n)가 아무리 커져도 사용하는 공간이 일정함(영어 소문자만 사용하므로 최대 26개의 키만 저장하면 됨)
41 changes: 41 additions & 0 deletions validate-binary-search-tree/taurus09318976.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 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

#val: 노드의 값, left: 왼쪽 자식 노드, right: 오른쪽 자식 노드
#helper 함수: 재귀적으로 BST의 유효성을 검사
#lower: 현재 노드의 값이 가져야 하는 최소값
#upper: 현재 노드의 값이 가져야 하는 최대값

class Solution:
def isValidBST(self, root: TreeNode):
def helper(node, lower=float('-inf'), upper=float('inf')):
if not node:
return True

# BST 조건 검사 현재 노드의 값이 허용되는 범위를 벗어나는지 확인(벗어나면 false 반환)
if node.val <= lower or node.val >= upper:
return False

# 왼쪽 서브트리 검사 (상한을 현재 노드의 값으로 설정)
if not helper(node.left, lower, node.val):
return False

# 오른쪽 서브트리 검사 (하한을 현재 노드의 값으로 설정)
if not helper(node.right, node.val, upper):
return False

return True

return helper(root)

#시간 복잡도: O(n)
#모든 노드를 한번씩 방문
#공간 복잡도: O(n)
#재귀 호출 스택의 깊이가 트리의 높이만큼 필요