Skip to content
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

[Helena] Week 8 #965

Merged
merged 5 commits into from
Feb 2, 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
28 changes: 28 additions & 0 deletions clone-graph/yolophg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Time Complexity: O(N + E) - visit each node once and for each node, we iterate through its neighbors O(E).
# Space Complexity: O(N) - store a copy of each node in the hashmap O(N).

class Solution:
def cloneGraph(self, node):
if node is None:
return None

# dictionary to keep track of cloned nodes (original -> clone)
mp = {}

def clone(node):
if node in mp:
# if the node has already been cloned, return the copy
return mp[node]

# create a new node with the same value
cpy = Node(node.val)
# store it in the map so don't clone it again
mp[node] = cpy

# clone all neighbors and add them to the new node's neighbors list
for n in node.neighbors:
cpy.neighbors.append(clone(n))

return cpy

return clone(node)
29 changes: 29 additions & 0 deletions longest-common-subsequence/yolophg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Time Complexity: O(m * n) - each (i, j) pair is computed once and stored, reducing redundant calls.
# Space Complexity: O(m * n) - memoization dictionary stores O(m * n) states.
# - Recursion stack depth is O(m + n) in the worst case.

class Solution:
def longestCommonSubsequence(self, t1: str, t2: str) -> int:
# to memoize results so we don't recompute the same subproblems
m = dict()

# recursive function to compute LCS
def s(i, j):
# base case: if we reach the end of either string, there's nothing left to compare
if i == len(t1) or j == len(t2):
return 0

# if already computed this state, just return the cached value
if (i, j) in m:
return m[(i, j)]

# if the characters match, we take this character and move diagonally
if t1[i] == t2[j]:
m[i, j] = 1 + s(i + 1, j + 1)
else:
# if they don't match, we either move forward in t1 or t2 and take the max
m[i, j] = max(s(i + 1, j), s(i, j + 1))

return m[i, j]

return s(0, 0)
27 changes: 27 additions & 0 deletions longest-repeating-character-replacement/yolophg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Time Complexity: O(n) - loop through the string once, and operations like `max(count.values())` are constant time because there are at most 26 characters.
# Space Complexity: O(1) - `count` only stores counts for up to 26 characters.

class Solution:
def characterReplacement(self, s: str, k: int) -> int:
# keep track of counts in the current window
count = {}

left, right = 0, 0
res = 0

# move the right pointer across the string
for right in range(len(s)):
# update the count for the character at the right pointer
count[s[right]] = count.get(s[right], 0) + 1

# if the window size minus the most frequent char count is bigger than k,
# need to shrink the window from the left
while (right - left + 1) - max(count.values()) > k:
# reduce the count of the char at the left pointer and move the left pointer
count[s[left]] -= 1
left += 1

# update the max length of the valid window
res = max(res, right - left + 1)

return res
15 changes: 15 additions & 0 deletions number-of-1-bits/yolophg.py
Copy link
Contributor

Choose a reason for hiding this comment

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

2로 나누었을 때 나머지가 1이면 1비트, 0이면 0비트 일테니 이런 식으로도 구분이 되겠군요 :)

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Time Complexity: O(k) - check each bit of n once. In the worst case, this is about 32 iterations.
# Space Complexity: O(1) - only use a constant amount of extra space.

class Solution:
def hammingWeight(self, n: int) -> int:
count = 0

# keep going till n becomes 0 (no more bits left to check)
while n:
# check if the last bit is 1 (n % 2 tells us this) and add it to the count
count += (n % 2)
# shift n to the right by 1 to move to the next bit
n = n >> 1

return count
22 changes: 22 additions & 0 deletions sum-of-two-integers/yolophg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Time Complexity: O(1) - fixed 32-bit operations, at most 32 iterations
# Space Complexity: O(1) - only uses a few integer variables

class Solution:
def getSum(self, a: int, b: int) -> int:
# 32-bit mask to keep numbers within range
mask = 0xFFFFFFFF
# max value for a signed 32-bit integer (2^31 - 1)
MAX = 0x7FFFFFFF

# keep going until there's no carry left
while b != 0:
# carry is AND operation, then shift left
carry = (a & b) << 1
# XOR does the addition, keep it within 32 bits
a = (a ^ b) & mask
# carry becomes the new b (loop continues if carry exists)
b = carry & mask

# if a is greater than MAX, it's actually a negative number in 32-bit terms
# convert it to proper negative representation
return a if a <= MAX else ~(a ^ mask)