Skip to content

Commit

Permalink
[bhyun-kim, 김병현] Week 10 solutions
Browse files Browse the repository at this point in the history
  • Loading branch information
bhyun-kim committed Jul 6, 2024
1 parent 42c41cd commit 97d65df
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 0 deletions.
52 changes: 52 additions & 0 deletions graph-valid-tree/bhyun-kim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
261. Graph Valid Tree
https://leetcode.com/problems/graph-valid-tree/
Solution:
To solve this problem, we can use the depth-first search (DFS) algorithm.
We can create an adjacency list to represent the graph.
Then, we can perform a DFS starting from node 0 to check if all nodes are visited.
If all nodes are visited, we return True; otherwise, we return False.
Time complexity: O(n)
- We visit each node once.
- The DFS has a time complexity of O(n).
Space complexity: O(n)
- We use an adjacency list to store the graph.
- The space complexity is O(n) for the adjacency list.
"""


from typing import List


class Solution:
def validTree(self, n: int, edges: List[List[int]]) -> bool:
if len(edges) != n - 1:
return False

# Initialize adjacency list
graph = {i: [] for i in range(n)}
for a, b in edges:
graph[a].append(b)
graph[b].append(a)

# Function to perform DFS
def dfs(node, parent):
visited.add(node)
for neighbor in graph[node]:
if neighbor == parent:
continue
if neighbor in visited or not dfs(neighbor, node):
return False
return True

visited = set()

# Start DFS from node 0
if not dfs(0, -1):
return False

# Check if all nodes are visited
return len(visited) == n
51 changes: 51 additions & 0 deletions house-robber-ii/bhyun-kim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
213. House Robber II
https://leetcode.com/problems/house-robber-ii/
Solution:
To solve this problem, we can use the dynamic programming approach.
We can create a helper function to solve the house robber problem for a given range of houses.
We consider two cases:
- Rob houses from 0 to n-2.
- Rob houses from 1 to n-1.
We return the maximum amount of money that can be robbed from these two cases.
Time complexity: O(n)
- We iterate through each house once.
- The helper function has a time complexity of O(n).
Space complexity: O(n)
- We use a dynamic programming array to store the maximum amount of money that can be robbed.
- The space complexity is O(n) for the dynamic programming array.
"""

from typing import List


class Solution:
def rob(self, nums: List[int]) -> int:
def rob_linear(houses):
if not houses:
return 0
if len(houses) == 1:
return houses[0]
dp = [0] * len(houses)
dp[0] = houses[0]
dp[1] = max(houses[0], houses[1])
for i in range(2, len(houses)):
dp[i] = max(dp[i - 1], houses[i] + dp[i - 2])
return dp[-1]

n = len(nums)
if n == 1:
return nums[0]
if n == 2:
return max(nums[0], nums[1])

# Case 1: Rob houses from 0 to n-2
case1 = rob_linear(nums[:-1])
# Case 2: Rob houses from 1 to n-1
case2 = rob_linear(nums[1:])

return max(case1, case2)
40 changes: 40 additions & 0 deletions house-robber/bhyun-kim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
198. House Robber
https://leetcode.com/problems/house-robber/
Solution:
To solve this problem, we can use the dynamic programming approach.
We can create a dynamic programming array to store the maximum amount of money that can be robbed.
We consider two cases:
- Rob the current house and the house two steps back.
- Skip the current house and rob the house one step back.
We return the maximum amount of money that can be robbed from these two cases.
Time complexity: O(n)
- We iterate through each house once.
- The dynamic programming array has a time complexity of O(n).
Space complexity: O(n)
- We use a dynamic programming array to store the maximum amount of money that can be robbed.
- The space complexity is O(n) for the dynamic programming array.
"""

from typing import List


class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
if len(nums) == 1:
return nums[0]

n = len(nums)
dp = [0] * n
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])

for i in range(2, n):
dp[i] = max(dp[i - 1], nums[i] + dp[i - 2])

return dp[-1]
43 changes: 43 additions & 0 deletions longest-palindromic-substring/bhyun-kim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
5. Longest Palindromic Substring
https://leetcode.com/problems/longest-palindromic-substring/
Solution:
To solve this problem, we can use the expand from center approach.
We can iterate through each character in the string and expand around it to find palindromes.
We handle both odd-length and even-length palindromes by checking two cases.
We return the longest palindrome found.
Time complexity: O(n^2)
- We iterate through each character in the string.
- For each character, we expand around it to find palindromes.
Space complexity: O(1)
- We use constant space to store the maximum palindrome found.
"""


class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s) <= 1:
return s

def expand_from_center(left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return s[left + 1 : right]

max_str = s[0]

for i in range(len(s) - 1):
odd = expand_from_center(i, i)
even = expand_from_center(i, i + 1)

if len(odd) > len(max_str):
max_str = odd
if len(even) > len(max_str):
max_str = even

return max_str
54 changes: 54 additions & 0 deletions number-of-connected-components-in-an-undirected-graph/bhyun-kim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
323. Number of Connected Components in an Undirected Graph
https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/
Solution:
To solve this problem, we can use the depth-first search (DFS) algorithm.
We can create an adjacency list to represent the graph.
Then, we can perform a DFS starting from each node to count the number of connected components.
We keep track of visited nodes to avoid revisiting nodes.
The number of connected components is the number of times we perform DFS.
Time complexity: O(n+m)
- We visit each node and edge once.
- The DFS has a time complexity of O(n+m).
Space complexity: O(n+m)
- We use an adjacency list to store the graph.
- The space complexity is O(n+m) for the adjacency list and visited set.
"""

from typing import List


class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
# Initialize the graph as an adjacency list
graph = {i: [] for i in range(n)}
for a, b in edges:
graph[a].append(b)
graph[b].append(a)

# Set to keep track of visited nodes
visited = set()

# Function to perform DFS
def dfs(node):
stack = [node]
while stack:
current = stack.pop()
for neighbor in graph[current]:
if neighbor not in visited:
visited.add(neighbor)
stack.append(neighbor)

# Count connected components
count = 0
for i in range(n):
if i not in visited:
count += 1
visited.add(i)
dfs(i)

return count

0 comments on commit 97d65df

Please sign in to comment.