Skip to main content

import heapq


class Solution:
def lastStoneWeight(self, stones: list[int]) -> int:
stones.append(0)
stones = list(map(lambda x: -x, stones))
heapq.heapify(stones)
while len(stones) > 1:
y, x = -heapq.heappop(stones), -heapq.heappop(stones)
if x != y:
heapq.heappush(stones, -(y - x))
return -heapq.heappop(stones)

class Solution1:
def backspaceCompare(self, s: str, t: str) -> bool:
ss, st = [], []
for c in s:
if c != '#':
ss.append(c)
elif ss:
ss.pop()
for c in t:
if c != '#':
st.append(c)
elif st:
st.pop()
return ss == st


class Solution:
def backspaceCompare(self, s: str, t: str) -> bool:
ps, pt = len(s) - 1, len(t) - 1 # pointer
bs, bt = 0, 0 # backspace

def go_left(string, pointer, backspace):
while pointer >= 0 and (backspace or string[pointer] == '#'):
backspace += (-1) ** (string[pointer] != '#')
pointer -= 1
return pointer, backspace

while True:
(ps, bs), (pt, bt) = go_left(s, ps, bs), go_left(t, pt, bt)
if not (ps >= 0 and pt >= 0 and s[ps] == t[pt]):
return ps == pt == -1
ps -= 1
pt -= 1

from collections import Counter


class Solution:
def getHint(self, s: str, g: str) -> str:
a, b = 0, 0
cs, cg = Counter(), Counter()
for i in range(len(s)):
if s[i] == g[i]:
a += 1
continue
if cg[s[i]]:
cg[s[i]] -= 1
b += 1
else:
cs[s[i]] += 1
if cs[g[i]]:
cs[g[i]] -= 1
b += 1
else:
cg[g[i]] += 1
return f'{a}A{b}B'

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 ()
)