Skip to main content

import math


class Solution1:
def uniquePaths(self, m: int, n: int) -> int:
return math.comb((m - 1) + (n - 1), (n - 1))


class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [1] + [0 for _ in range(n - 1)]
for _ in range(m):
for i in range(n - 1):
dp[i + 1] += dp[i]
return dp[n - 1]

class Solution:
# https://leetcode.com/problems/longest-repeating-character-replacement/solutions/278271
def characterReplacement(self, s: str, k: int) -> int:
c, mf = {}, 0 # counter, max_freq
l, N = 0, len(s)
for r in range(N):
c[s[r]] = c.get(s[r], 0) + 1
mf = max(mf, c[s[r]])
if not ((r + 1) - l - mf <= k): # shift right
c[s[l]] -= 1
l += 1
# find next if same
return N - l # length


class Solution2:
# https://leetcode.com/problems/longest-repeating-character-replacement/solutions/278271
def characterReplacement(self, s: str, k: int) -> int:
result = 0
c, mf = {}, 0 # counter, max_freq
for r in range(len(s)):
c[s[r]] = c.get(s[r], 0) + 1
mf = max(mf, c[s[r]])
if result - mf >= k:
c[s[r - result]] -= 1
else:
result += 1 # update when more
return result


class SolutionBS: # TODO: review
# https://leetcode.com/problems/longest-repeating-character-replacement/solutions/2805777
def characterReplacement(self, s: str, k: int) -> int:
def too_long(length: int):
c, mf = {}, 0
l = 0
for r in range(len(s)):
c[s[r]] = c.get(s[r], 0) + 1
if r + 1 - l > length:
c[s[l]] -= 1
l += 1
mf = max(mf, c[s[r]])
if length - mf <= k:
return False
return True

l, r = 0, len(s)
while l < r:
m = (l + r) // 2
length = m + 1
l, r = (l, m) if too_long(length) else (m + 1, r)
return (l - 1) + 1

class Solution:
def computeArea(
self,
ax1: int,
ay1: int,
ax2: int,
ay2: int,
bx1: int,
by1: int,
bx2: int,
by2: int,
) -> int:
(ax1, ax2), (ay1, ay2), (bx1, bx2), (by1, by2) = map(
sorted,
((ax1, ax2), (ay1, ay2), (bx1, bx2), (by1, by2)),
)
return sum(
(
(ax2 - ax1) * (ay2 - ay1),
(bx2 - bx1) * (by2 - by1),
-(
max(0, min(ax2, bx2) - max(ax1, bx1))
* max(0, min(ay2, by2) - max(ay1, by1))
),
)
)

# The guess API is already defined for you.
# @param num, your guess
# @return -1 if num is higher than the picked number
# 1 if num is lower than the picked number
# otherwise return 0
def guess(num: int) -> int:
...


class Solution:
def guessNumber(self, n: int) -> int:
l, r = 0, n
while l < r:
m = (l + r) // 2
if not guess(m):
return m
l, r = (l, m) if guess(m) < 0 else (m + 1, r)
return l

class Solution:
def numIslands(self, grid) -> int:
M, N = len(grid), len(grid[0])

def dfs(m, n):
r = 0 <= m < M and 0 <= n < N and grid[m][n] == '1'
if r:
grid[m][n] = None
list(map(dfs, (m + 1, m - 1, m, m), (n, n, n + 1, n - 1)))
return r

return sum(dfs(m, n) for m in range(M) for n in range(N))

class Solution:
def floodFill(
self, image: list[list[int]], sr: int, sc: int, color: int
) -> list[list[int]]:
COLOR, M, N = image[sr][sc], len(image), len(image[0])

def dfs(m, n):
if not all([0 <= m < M, 0 <= n < N]):
return

if not all([image[m][n] == COLOR, image[m][n] != color]):
return

image[m][n] = color
list(map(dfs, (m + 1, m - 1, m, m), (n, n, n + 1, n - 1)))

dfs(sr, sc)
return image

class Solution1:
def removeDuplicates(self, nums: list[int]) -> int:
v, p = -101, 0 # ng
for i in range(len(nums)):
if nums[i] > v:
v = nums[p] = nums[i]
p += 1
return p


class Solution:
def removeDuplicates(self, nums: list[int]) -> int:
p = 1
for i in range(1, len(nums)):
if nums[p - 1] < nums[i]:
nums[p], p = nums[i], p + 1
return p

# 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, lo=float('-inf'), hi=float('inf')) -> bool:
'''
[5,4,6,null,null,3,7] => false
'''
return (not root) or all(
[
lo < root.val < hi,
self.isValidBST(root.left, lo, root.val),
self.isValidBST(root.right, root.val, hi),
]
)

from functools import reduce


# 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 levelOrder(self, root) -> list[list[int]]:
result, q = [], [root]
while True:
q = [x for x in q if x]
v = [x.val for x in q]
if not v:
break
result.append(v)
q = reduce(lambda a, b: a + [b.left, b.right], q, [])
return result

class Solution:
def search(self, nums: list[int], target: int) -> int:
l, r = 0, len(nums)
while l < r:
m = (l + r) // 2
if nums[m] == target:
return m
l, r = (l, m) if nums[m] > target else (m + 1, r)
return -1

class Solution:
def detectCycle(self, head):
'''
.___a___.___C-b___.
(_________) -> C: cycle
b

slow: a+C-b + xC
fast: a+C-b + yC

2 slow = fast
=> a+C-b = (y-2x)C
=> a = (y-2x-1)C+b

.___(y-2x-1)C+b___.___C-b___.
(_________)
b

=> a mod C = b mod C
'''
l = r = head
while r and r.next:
l, r = l.next, r.next.next
if l is r:
break
else:
return

while head is not r:
head, r = head.next, r.next
return head

"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""


class Solution:
def preorder(self, root):
return (
(root.val,) + sum((self.preorder(x) for x in root.children), ())
if root
else ()
)