"""
Structure:
Each problem is annotated with:
# ==== <ID>. <Problem Title> (Platform – Difficulty – Topic) ====
Followed by a function / class‑based solution.
Notes:
* All solutions run in O(accepted) time/space per canonical discussions.
* LeetCode problem numbers kept for easy cross‑reference.
* Some platforms (CodeChef / Codeforces) have equivalent statements; the
algorithms provided pass the canonical version.
"""
# ========================== EASY (10) ===============================
# 1. Two Sum (LeetCode #1 – Easy – Array/Hash Map)
def twoSum(nums, target):
table = {}
for i, x in enumerate(nums):
if target - x in table:
return [table[target - x], i]
table[x] = i
# 2. Remove Duplicates from Sorted Array (#26)
def removeDuplicates(nums):
if not nums:
return 0
i = 0
for j in range(1, len(nums)):
if nums[j] != nums[i]:
i += 1
nums[i] = nums[j]
return i + 1
# 3. Plus One (#66)
def plusOne(digits):
for i in reversed(range(len(digits))):
if digits[i] == 9:
digits[i] = 0
else:
digits[i] += 1
return digits
return [1] + digits
# 4. Merge Sorted Array (#88)
def mergeSortedArray(nums1, m, nums2, n):
while m and n:
if nums1[m-1] > nums2[n-1]:
nums1[m+n-1] = nums1[m-1]
m -= 1
else:
nums1[m+n-1] = nums2[n-1]
n -= 1
nums1[:n] = nums2[:n]
# 5. Transpose Matrix (#867)
def transpose(matrix):
return [list(col) for col in zip(*matrix)]
# 6. Pascal’s Triangle (#118)
def pascal(numRows):
res = [[1]]
for _ in range(1, numRows):
prev = res[-1]
res.append([1] + [prev[i] + prev[i+1] for i in range(len(prev)-1)] + [1])
return res
# 7. Climbing Stairs (#70)
def climbStairs(n):
a, b = 1, 1
for _ in range(n):
a, b = b, a + b
return a
# 8. Happy Number (#202)
def isHappy(n):
seen = set()
while n != 1 and n not in seen:
seen.add(n)
n = sum(int(c)**2 for c in str(n))
return n == 1
# 9. Missing Number (#268)
def missingNumber(nums):
n = len(nums)
return n*(n+1)//2 - sum(nums)
# 10. Delete Columns to Make Sorted (#944)
def minDeletionSize(strs):
return sum(list(col) != sorted(col) for col in zip(*strs))
# ========================== MEDIUM (80) =============================
# ---------- Array (15) ----------
# 11. Find First and Last Position (#34)
def searchRange(nums, target):
def bound(left):
lo, hi = 0, len(nums)
while lo < hi:
mid = (lo+hi)//2
if nums[mid] < target or (left and nums[mid] == target):
lo = mid + 1
else:
hi = mid
return lo
l = bound(False)
if l == len(nums) or nums[l] != target:
return [-1, -1]
return [l, bound(True)-1]
# 12. Next Permutation (#31)
def nextPermutation(nums):
i = len(nums)-2
while i >= 0 and nums[i] >= nums[i+1]:
i -= 1
if i >= 0:
j = len(nums)-1
while nums[j] <= nums[i]:
j -= 1
nums[i], nums[j] = nums[j], nums[i]
nums[i+1:] = reversed(nums[i+1:])
# 13. Product of Array Except Self (#238)
def productExceptSelf(nums):
res = [1]*len(nums)
prefix = 1
for i in range(len(nums)):
res[i] = prefix
prefix *= nums[i]
suffix = 1
for i in reversed(range(len(nums))):
res[i] *= suffix
suffix *= nums[i]
return res
# 14. Subarray Sum Equals K (#560)
from collections import defaultdict
def subarraySum(nums, k):
count = defaultdict(int); count[0] = 1
acc = ans = 0
for x in nums:
acc += x
ans += count[acc - k]
count[acc] += 1
return ans
# 15. Set Matrix Zeroes (#73)
def setZeroes(matrix):
R, C = len(matrix), len(matrix[0])
first_row_zero = any(matrix[0][j] == 0 for j in range(C))
first_col_zero = any(matrix[i][0] == 0 for i in range(R))
for i in range(1, R):
for j in range(1, C):
if matrix[i][j] == 0:
matrix[i][0] = matrix[0][j] = 0
for i in range(1, R):
for j in range(1, C):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
if first_row_zero:
for j in range(C):
matrix[0][j] = 0
if first_col_zero:
for i in range(R):
matrix[i][0] = 0
# 16. Spiral Matrix (#54)
def spiralOrder(matrix):
res = []
while matrix:
res += matrix.pop(0)
matrix = list(zip(*matrix))[::-1]
return res
# 17. Search in Rotated Sorted Array (#33)
def search(nums, target):
lo, hi = 0, len(nums)-1
while lo <= hi:
mid = (lo+hi)//2
if nums[mid] == target:
return mid
if nums[lo] <= nums[mid]:
if nums[lo] <= target < nums[mid]:
hi = mid-1
else:
lo = mid+1
else:
if nums[mid] < target <= nums[hi]:
lo = mid+1
else:
hi = mid-1
return -1
# 18. 3Sum (#15)
def threeSum(nums):
nums.sort()
res = []
for i, a in enumerate(nums):
if i and a == nums[i-1]:
continue
l, r = i+1, len(nums)-1
while l < r:
s = a + nums[l] + nums[r]
if s == 0:
res.append([a, nums[l], nums[r]])
l += 1
while l < r and nums[l] == nums[l-1]:
l += 1
elif s < 0:
l += 1
else:
r -= 1
return res
# 19. Container With Most Water (#11)
def maxArea(height):
l, r, best = 0, len(height)-1, 0
while l < r:
best = max(best, (r-l)*min(height[l], height[r]))
if height[l] < height[r]:
l += 1
else:
r -= 1
return best
# 20. Trapping Rain Water (#42)
def trap(height):
l, r = 0, len(height)-1
left_max = right_max = 0
water = 0
while l < r:
if height[l] < height[r]:
left_max = max(left_max, height[l])
water += left_max - height[l]
l += 1
else:
right_max = max(right_max, height[r])
water += right_max - height[r]
r -= 1
return water
# 21. Minimum Size Subarray Sum (#209)
def minSubArrayLen(target, nums):
l = total = res = 0
res = float('inf')
for r, x in enumerate(nums):
total += x
while total >= target:
res = min(res, r - l + 1)
total -= nums[l]
l += 1
return 0 if res == float('inf') else res
# 22. Sort Colors (#75)
def sortColors(nums):
l, r, i = 0, len(nums)-1, 0
while i <= r:
if nums[i] == 0:
nums[l], nums[i] = nums[i], nums[l]
l += 1; i += 1
elif nums[i] == 2:
nums[r], nums[i] = nums[i], nums[r]
r -= 1
else:
i += 1
# 23. Merge Intervals (#56)
def mergeIntervals(intervals):
intervals.sort(key=lambda x: x[0])
merged = []
for iv in intervals:
if not merged or merged[-1][1] < iv[0]:
merged.append(iv)
else:
merged[-1][1] = max(merged[-1][1], iv[1])
return merged
# 24. Longest Consecutive Sequence (#128)
def longestConsecutive(nums):
s = set(nums)
best = 0
for x in nums:
if x-1 not in s:
y = x
while y in s:
y += 1
best = max(best, y - x)
return best
# 25. Top K Frequent Elements (#347)
import heapq, collections
def topKFrequent(nums, k):
count = collections.Counter(nums)
return [x for x, _ in heapq.nlargest(k, count.items(), key=lambda p: p[1])]
# ---------- String (15) ----------
# 26. Longest Substring Without Repeating Characters (#3)
def lengthOfLongestSubstring(s):
seen = {}
l = ans = 0
for r, ch in enumerate(s):
if ch in seen and seen[ch] >= l:
l = seen[ch] + 1
seen[ch] = r
ans = max(ans, r - l + 1)
return ans
# 27. Valid Parentheses (#20)
def isValidParentheses(s):
stack = []
match = {')':'(', '}':'{', ']':'['}
for ch in s:
if ch in match.values():
stack.append(ch)
elif not stack or stack.pop() != match[ch]:
return False
return not stack
# 28. Longest Palindromic Substring (#5)
def longestPalindrome(s):
res = ""
for i in range(len(s)):
for l, r in [(i, i), (i, i+1)]:
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1; r += 1
if r - l - 1 > len(res):
res = s[l+1:r]
return res
# 29. Minimum Window Substring (#76)
from collections import Counter
def minWindow(s, t):
need = Counter(t)
missing = len(t)
l = start = end = 0
for r, ch in enumerate(s, 1):
if need[ch] > 0:
missing -= 1
need[ch] -= 1
if not missing:
while l < r and need[s[l]] < 0:
need[s[l]] += 1; l += 1
if end == 0 or r - l < end - start:
start, end = l, r
need[s[l]] += 1; missing += 1; l += 1
return s[start:end]
# 30. Group Anagrams (#49)
def groupAnagrams(strs):
ans = collections.defaultdict(list)
for s in strs:
ans[tuple(sorted(s))].append(s)
return list(ans.values())
# 31. Decode String (#394)
def decodeString(s):
stack = []
cur = ""
num = 0
for ch in s:
if ch.isdigit():
num = num*10 + int(ch)
elif ch == '[':
stack.append((cur, num))
cur, num = "", 0
elif ch == ']':
prev, k = stack.pop()
cur = prev + cur*k
else:
cur += ch
return cur
# 32. Count and Say (#38)
def countAndSay(n):
res = "1"
for _ in range(n-1):
cur, cnt, next_res = res[0], 0, ""
for ch in res:
if ch == cur:
cnt += 1
else:
next_res += str(cnt) + cur
cur, cnt = ch, 1
next_res += str(cnt) + cur
res = next_res
return res
# 33. Valid Anagram (#242)
def isAnagram(s, t):
return sorted(s) == sorted(t)
# 34. Word Pattern (#290)
def wordPattern(pattern, s):
words = s.split()
if len(pattern) != len(words):
return False
p2w, w2p = {}, {}
for p, w in zip(pattern, words):
if p in p2w and p2w[p] != w:
return False
if w in w2p and w2p[w] != p:
return False
p2w[p] = w; w2p[w] = p
return True
# 35. Longest Common Subsequence (#1143)
def longestCommonSubsequence(text1, text2):
m, n = len(text1), len(text2)
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(m-1, -1, -1):
for j in range(n-1, -1, -1):
if text1[i] == text2[j]:
dp[i][j] = 1 + dp[i+1][j+1]
else:
dp[i][j] = max(dp[i+1][j], dp[i][j+1])
return dp[0][0]
# 36. Palindromic Substrings (#647)
def countSubstrings(s):
ans = 0
for i in range(len(s)):
for l, r in [(i, i), (i, i+1)]:
while l >= 0 and r < len(s) and s[l] == s[r]:
ans += 1; l -= 1; r += 1
return ans
# 37. String to Integer (atoi) (#8)
def myAtoi(s):
s = s.lstrip()
if not s: return 0
sign = -1 if s[0] == '-' else 1
if s[0] in '+-': s = s[1:]
num = 0
for ch in s:
if not ch.isdigit(): break
num = num*10 + int(ch)
num *= sign
INT_MAX, INT_MIN = 2**31-1, -2**31
return max(INT_MIN, min(INT_MAX, num))
# 38. Implement Trie (Prefix Tree) (#208)
class TrieNode:
__slots__ = ('children', 'word')
def __init__(self):
self.children = {}
self.word = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for ch in word:
node = node.children.setdefault(ch, TrieNode())
node.word = True
def search(self, word):
node = self._find(word)
return node.word if node else False
def startsWith(self, prefix):
return bool(self._find(prefix))
def _find(self, s):
node = self.root
for ch in s:
if ch not in node.children:
return None
node = node.children[ch]
return node
# 39. Longest Word in Dictionary through Deleting (#524)
def findLongestWord(s, d):
def is_subseq(word):
it = iter(s)
return all(ch in it for ch in word)
best = ""
for w in d:
if is_subseq(w):
if len(w) > len(best) or (len(w) == len(best) and w < best):
best = w
return best
# 40. Sentence Similarity (#734)
def areSentencesSimilar(sentence1, sentence2, pairs):
if len(sentence1) != len(sentence2):
return False
sim = collections.defaultdict(set)
for a, b in pairs:
sim[a].add(b); sim[b].add(a)
return all(w1 == w2 or w2 in sim[w1] for w1, w2 in zip(sentence1, sentence2))
# ---------- Matrix (10) ----------
# 41. Word Search (#79)
def exist(board, word):
R, C = len(board), len(board[0])
path = set()
def dfs(r, c, i):
if i == len(word): return True
if not (0 <= r < R and 0 <= c < C) or word[i] != board[r][c] or (r, c) in path:
return False
path.add((r, c))
res = any(dfs(r+dr, c+dc, i+1) for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)])
path.remove((r, c))
return res
for r in range(R):
for c in range(C):
if dfs(r, c, 0): return True
return False
# 42. Number of Islands (#200)
def numIslands(grid):
R, C = len(grid), len(grid[0])
def dfs(r, c):
if 0 <= r < R and 0 <= c < C and grid[r][c] == '1':
grid[r][c] = '0'
for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
dfs(r+dr, c+dc)
count = 0
for r in range(R):
for c in range(C):
if grid[r][c] == '1':
count += 1
dfs(r, c)
return count
# 43. 01 Matrix (#542)
from collections import deque
def updateMatrix(mat):
R, C = len(mat), len(mat[0])
q = deque()
dist = [[None]*C for _ in range(R)]
for r in range(R):
for c in range(C):
if mat[r][c] == 0:
dist[r][c] = 0
q.append((r,c))
while q:
r, c = q.popleft()
for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
nr, nc = r+dr, c+dc
if 0 <= nr < R and 0 <= nc < C and dist[nr][nc] is None:
dist[nr][nc] = dist[r][c] + 1
q.append((nr, nc))
return dist
# 44. Rotate Image (#48)
def rotate(matrix):
matrix[:] = zip(*matrix[::-1])
# 45. Search a 2D Matrix (#74)
def searchMatrix(matrix, target):
if not matrix: return False
R, C = len(matrix), len(matrix[0])
lo, hi = 0, R*C-1
while lo <= hi:
mid = (lo+hi)//2
val = matrix[mid//C][mid% C]
if val == target:
return True
elif val < target:
lo = mid + 1
else:
hi = mid - 1
return False
# 46. The Skyline Problem (#218)
import heapq
def getSkyline(buildings):
events = sorted([(l, -h, r) for l, r, h in buildings] + [(r, 0, None) for _, r, _ in buildings])
res = [[0, 0]]
live = [(0, float('inf'))]
for x, negH, r in events:
while live[0][1] <= x:
heapq.heappop(live)
if negH:
heapq.heappush(live, (negH, r))
if res[-1][1] != -live[0][0]:
res.append([x, -live[0][0]])
return res[1:]
# 47. Max Sum Rectangle No Larger Than K (#363)
def maxSumSubmatrix(matrix, k):
import bisect
R, C = len(matrix), len(matrix[0])
ans = float('-inf')
for top in range(R):
col_sum = [0]*C
for bottom in range(top, R):
for c in range(C):
col_sum[c] += matrix[bottom][c]
prefix, accu = [0], 0
for s in col_sum:
accu += s
idx = bisect.bisect_left(prefix, accu - k)
if idx < len(prefix):
ans = max(ans, accu - prefix[idx])
bisect.insort(prefix, accu)
return ans
# 48. Diagonal Traverse (#498)
def findDiagonalOrder(mat):
if not mat: return []
R, C = len(mat), len(mat[0])
res = []
for d in range(R + C - 1):
intermediate = []
r = 0 if d < C else d - C + 1
c = d if d < C else C - 1
while r < R and c >= 0:
intermediate.append(mat[r][c])
r += 1; c -= 1
if d % 2 == 0:
res.extend(intermediate[::-1])
else:
res.extend(intermediate)
return res
# 49. Rotate Image II (variant) – similar to #44
# ---------- Math / Number Theory (10) ----------
# 49. Add Binary (#67)
def addBinary(a, b):
i, j, carry, res = len(a)-1, len(b)-1, 0, []
while i >=0 or j>=0 or carry:
s = carry
if i>=0: s += int(a[i]); i -= 1
if j>=0: s += int(b[j]); j -= 1
res.append(str(s%2)); carry = s//2
return ''.join(reversed(res))
# 50. Sqrt(x) (#69)
def mySqrt(x):
if x < 2: return x
lo, hi = 1, x//2
while lo <= hi:
mid = (lo+hi)//2
if mid*mid <= x < (mid+1)*(mid+1):
return mid
elif mid*mid > x:
hi = mid-1
else:
lo = mid+1
# 51. Permutations (#46)
def permute(nums):
res = [[]]
for x in nums:
res = [p[:i]+[x]+p[i:] for p in res for i in range(len(p)+1)]
return res
# 52. Pow(x, n) (#50)
def myPow(x, n):
if n < 0:
x, n = 1/x, -n
ans = 1
while n:
if n & 1:
ans *= x
x *= x
n >>= 1
return ans
# 53. Factorial Trailing Zeroes (#172)
def trailingZeroes(n):
ans = 0
while n:
n //= 5
ans += n
return ans
# 54. Ugly Number II (#264)
def nthUglyNumber(n):
ugly = [1]
i2 = i3 = i5 = 0
for _ in range(1, n):
nxt = min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
ugly.append(nxt)
if nxt == ugly[i2]*2: i2 += 1
if nxt == ugly[i3]*3: i3 += 1
if nxt == ugly[i5]*5: i5 += 1
return ugly[-1]
# 55. Count Primes (#204)
def countPrimes(n):
if n < 2: return 0
sieve = bytearray(b'') * n
sieve[:2] = b''
for i in range(2, int(n**0.5)+1):
if sieve[i]:
sieve[i*i:n:i] = b'' * len(sieve[i*i:n:i])
return sum(sieve)
# 56. Fraction to Recurring Decimal (#166)
def fractionToDecimal(numerator, denominator):
if numerator % denominator == 0:
return str(numerator // denominator)
sign = '-' if (numerator < 0) ^ (denominator < 0) else ''
numerator, denominator = abs(numerator), abs(denominator)
res = sign + str(numerator // denominator) + '.'
numerator %= denominator
lookup = {}
while numerator:
if numerator in lookup:
idx = lookup[numerator]
return res[:idx] + '(' + res[idx:] + ')'
lookup[numerator] = len(res)
numerator *= 10
res += str(numerator // denominator)
numerator %= denominator
return res
# 57. Excel Sheet Column Number (#171)
def titleToNumber(columnTitle):
res = 0
for ch in columnTitle:
res = res*26 + ord(ch)-64
return res
# 58. Prime Palindrome (#866)
def primePalindrome(n):
import sympy as sp
i = n
while True:
s = str(i)
if s == s[::-1] and sp.isprime(i):
return i
i += 1
# ---------- Dynamic Programming (15) ----------
# 59. Edit Distance (#72)
def minDistance(word1, word2):
m, n = len(word1), len(word2)
dp = list(range(n+1))
for i in range(1, m+1):
prev, dp[0] = i-1, i
for j in range(1, n+1):
prev, dp[j] = dp[j], prev if word1[i-1]==word2[j-1] else 1+min(prev, dp[j], dp[j-1])
return dp[n]
# 60. Decode Ways (#91)
def numDecodings(s):
if not s or s[0]=='0': return 0
a = b = 1
for i in range(1,len(s)):
tmp = 0
if s[i]!='0':
tmp = b
if 10 <= int(s[i-1:i+1]) <= 26:
tmp += a
a, b = b, tmp
return b
# 61. Unique Paths (#62)
def uniquePaths(m, n):
from math import comb
return comb(m+n-2, n-1)
# 62. Coin Change (#322)
def coinChange(coins, amount):
dp = [amount+1]*(amount+1)
dp[0] = 0
for coin in coins:
for x in range(coin, amount+1):
dp[x] = min(dp[x], dp[x-coin]+1)
return dp[amount] if dp[amount]<=amount else -1
# 63. Longest Increasing Subsequence (#300)
def lengthOfLIS(nums):
import bisect
tails = []
for x in nums:
idx = bisect.bisect_left(tails, x)
if idx == len(tails):
tails.append(x)
else:
tails[idx] = x
return len(tails)
# 64. House Robber (#198)
def rob(nums):
prev = curr = 0
for x in nums:
prev, curr = curr, max(curr, prev + x)
return curr
# 65. Maximum Subarray (#53)
def maxSubArray(nums):
best = cur = nums[0]
for x in nums[1:]:
cur = x if cur < 0 else cur + x
best = max(best, cur)
return best
# 66. Partition Equal Subset Sum (#416)
def canPartition(nums):
total = sum(nums)
if total % 2: return False
target = total // 2
dp = {0}
for x in nums:
dp |= {x+y for y in dp if x+y <= target}
return target in dp
# 67. Egg Dropping Problem (#887)
def superEggDrop(k, n):
dp = [0]*(k+1)
moves = 0
while dp[k] < n:
moves += 1
for i in range(k, 0, -1):
dp[i] += dp[i-1] + 1
return moves
# 68. Word Break (#139)
def wordBreak(s, wordDict):
wl = set(wordDict)
dp = [False]*(len(s)+1); dp[0] = True
for i in range(1, len(s)+1):
for j in range(i):
if dp[j] and s[j:i] in wl:
dp[i] = True; break
return dp[-1]
# 69. Largest Divisible Subset (#368)
def largestDivisibleSubset(nums):
if not nums: return []
nums.sort()
dp = [1]*len(nums)
prev = [-1]*len(nums)
max_idx = 0
for i in range(len(nums)):
for j in range(i):
if nums[i]%nums[j]==0 and dp[j]+1>dp[i]:
dp[i]=dp[j]+1; prev[i]=j
if dp[i]>dp[max_idx]: max_idx=i
res = []
while max_idx!=-1:
res.append(nums[max_idx])
max_idx = prev[max_idx]
return res[::-1]
# 70. Range Sum Query – Mutable (#307)
class NumArray:
def __init__(self, nums):
self.n = len(nums)
self.bit = [0]*(self.n+1)
for i, x in enumerate(nums):
self._add(i+1, x)
def _add(self, i, delta):
while i <= self.n:
self.bit[i] += delta
i += i & -i
def update(self, i, val):
cur = self.sumRange(i, i)
self._add(i+1, val - cur)
def _sum(self, i):
s = 0
while i:
s += self.bit[i]
i -= i & -i
return s
def sumRange(self, l, r):
return self._sum(r+1) - self._sum(l)
# 71. Russian Doll Envelopes (#354)
def maxEnvelopes(envelopes):
envelopes.sort(key=lambda x: (x[0], -x[1]))
return lengthOfLIS([h for _, h in envelopes])
# 72. Burst Balloons (#312)
def maxCoins(nums):
nums = [1] + nums + [1]
n = len(nums)
dp = [[0]*n for _ in range(n)]
for length in range(2, n):
for l in range(n - length):
r = l + length
dp[l][r] = max(nums[l]*nums[i]*nums[r] + dp[l][i] + dp[i][r] for i in range(l+1, r))
return dp[0][n-1]
# ---------- Graphs / Trees (10) ----------
# 73. Clone Graph (#133)
class Node:
def __init__(self, val, neighbors=None):
self.val = val
self.neighbors = neighbors or []
def cloneGraph(node):
if not node: return None
clones = {}
def dfs(n):
if n in clones: return clones[n]
clone = Node(n.val)
clones[n] = clone
clone.neighbors = [dfs(nei) for nei in n.neighbors]
return clone
return dfs(node)
# 74. Course Schedule (#207)
def canFinish(numCourses, prerequisites):
graph = collections.defaultdict(list)
indeg = [0]*numCourses
for a,b in prerequisites:
graph[b].append(a); indeg[a]+=1
queue = collections.deque([i for i in range(numCourses) if indeg[i]==0])
visited = 0
while queue:
cur = queue.popleft(); visited += 1
for nei in graph[cur]:
indeg[nei]-=1
if indeg[nei]==0: queue.append(nei)
return visited==numCourses
# 75. Binary Tree Level Order Traversal (#102)
def levelOrder(root):
if not root: return []
res, q = [], collections.deque([root])
while q:
lvl = []
for _ in range(len(q)):
node = q.popleft(); lvl.append(node.val)
if node.left: q.append(node.left)
if node.right: q.append(node.right)
res.append(lvl)
return res
# 76. Construct Binary Tree from Inorder & Postorder (#106)
def buildTree(inorder, postorder):
if not inorder: return None
root_val = postorder.pop()
idx = inorder.index(root_val)
root = TreeNode(root_val)
root.right = buildTree(inorder[idx+1:], postorder)
root.left = buildTree(inorder[:idx], postorder)
return root
# 77. Serialize and Deserialize Binary Tree (#297)
class Codec:
def serialize(self, root):
vals = []
def pre(node):
if node:
vals.append(str(node.val))
pre(node.left); pre(node.right)
else:
vals.append('#')
pre(root)
return ' '.join(vals)
def deserialize(self, data):
vals = iter(data.split())
def build():
val = next(vals)
if val == '#': return None
node = TreeNode(int(val))
node.left = build(); node.right = build()
return node
return build()
# 78. Number of Connected Components in Graph (#323)
def countComponents(n, edges):
parent = list(range(n))
def find(x):
if parent[x]!=x:
parent[x]=find(parent[x])
return parent[x]
for a,b in edges:
parent[find(a)] = find(b)
return sum(i==parent[i] for i in range(n))
# 79. Graph Valid Tree (#261)
def validTree(n, edges):
if len(edges)!=n-1: return False
return countComponents(n, edges)==1
# 80. Word Ladder (#127)
def ladderLength(beginWord, endWord, wordList):
wordSet = set(wordList)
if endWord not in wordSet: return 0
q = collections.deque([(beginWord,1)])
while q:
word, steps = q.popleft()
if word == endWord: return steps
for i in range(len(word)):
for ch in 'abcdefghijklmnopqrstuvwxyz':
nxt = word[:i]+ch+word[i+1:]
if nxt in wordSet:
wordSet.remove(nxt)
q.append((nxt, steps+1))
return 0
# 81. Minimum Height Trees (#310)
def findMinHeightTrees(n, edges):
if n==1: return [0]
graph = collections.defaultdict(set)
for a,b in edges:
graph[a].add(b); graph[b].add(a)
leaves = [i for i in range(n) if len(graph[i])==1]
remaining = n
while remaining>2:
remaining -= len(leaves)
new_leaves = []
for leaf in leaves:
nei = graph[leaf].pop()
graph[nei].remove(leaf)
if len(graph[nei])==1:
new_leaves.append(nei)
leaves = new_leaves
return leaves
# 82. Alien Dictionary (#269)
def alienOrder(words):
graph = collections.defaultdict(set)
indeg = {ch:0 for word in words for ch in word}
for a,b in zip(words, words[1:]):
for x,y in zip(a,b):
if x!=y:
if y not in graph[x]:
graph[x].add(y); indeg[y]+=1
break
else:
if len(b)<len(a): return ""
q = collections.deque([c for c in indeg if indeg[c]==0])
order = ''
while q:
c = q.popleft(); order += c
for nei in graph[c]:
indeg[nei]-=1
if indeg[nei]==0:
q.append(nei)
return order if len(order)==len(indeg) else ""
# ---------- Bit Manipulation (5) ----------
# 83. Single Number (#136)
def singleNumber(nums):
ans = 0
for x in nums:
ans ^= x
return ans
# 84. Number of 1 Bits (#191)
def hammingWeight(n):
cnt = 0
while n:
n &= n-1
cnt += 1
return cnt
# 85. Bitwise AND of Numbers Range (#201)
def rangeBitwiseAnd(left, right):
shift = 0
while left!=right:
left >>= 1; right >>= 1; shift += 1
return left << shift
# 86. Reverse Bits (#190)
def reverseBits(n):
ans = 0
for _ in range(32):
ans = (ans<<1) | (n & 1)
n >>= 1
return ans
# 87. Power of Two (#231)
def isPowerOfTwo(n):
return n>0 and (n & (n-1))==0
# ========================== HARD (10) ==============================
# 88. Median of Two Sorted Arrays (#4)
def findMedianSortedArrays(A, B):
if len(A) > len(B):
A, B = B, A
m, n = len(A), len(B)
imin, imax, half = 0, m, (m+n+1)//2
while imin <= imax:
i = (imin+imax)//2
j = half - i
if i < m and B[j-1] > A[i]:
imin = i + 1
elif i > 0 and A[i-1] > B[j]:
imax = i - 1
else:
if i==0: max_of_left = B[j-1]
elif j==0: max_of_left = A[i-1]
else: max_of_left = max(A[i-1], B[j-1])
if (m+n)%2: return max_of_left
if i==m: min_of_right = B[j]
elif j==n: min_of_right = A[i]
else: min_of_right = min(A[i], B[j])
return (max_of_left + min_of_right)/2
# 89. Sliding Window Maximum (#239)
def maxSlidingWindow(nums, k):
q = collections.deque()
res = []
for i, x in enumerate(nums):
while q and nums[q[-1]] <= x:
q.pop()
q.append(i)
if q[0] == i - k:
q.popleft()
if i >= k-1:
res.append(nums[q[0]])
return res
# 90. Longest Duplicate Substring (#1044)
def longestDupSubstring(s):
import functools, hashlib
n = len(s)
nums = [ord(c)-97 for c in s]
a = 26
mod = 2**63-1
def check(L):
h = 0
for i in range(L):
h = (h*a + nums[i]) % mod
seen = {h}
aL = pow(a, L, mod)
for start in range(1, n-L+1):
h = (h*a - nums[start-1]*aL + nums[start+L-1]) % mod
if h in seen:
return start
seen.add(h)
return -1
lo, hi, res = 1, n-1, ""
while lo <= hi:
mid = (lo+hi)//2
pos = check(mid)
if pos != -1:
res = s[pos:pos+mid]
lo = mid + 1
else:
hi = mid - 1
return res
# 91. Kth Largest Element in an Array (#215)
def findKthLargest(nums, k):
return heapq.nlargest(k, nums)[-1]
# 92. Wildcard Matching (#44)
def isMatch(s, p):
m, n = len(s), len(p)
dp = [[False]*(n+1) for _ in range(m+1)]
dp[0][0] = True
for j in range(1, n+1):
dp[0][j] = dp[0][j-1] and p[j-1]=='*'
for i in range(1, m+1):
for j in range(1, n+1):
if p[j-1] in {s[i-1], '?'}:
dp[i][j] = dp[i-1][j-1]
elif p[j-1]=='*':
dp[i][j] = dp[i-1][j] or dp[i][j-1]
return dp[m][n]
# 93. Minimum Window Subsequence (#727)
def minWindowSubsequence(S, T):
m, n = len(S), len(T)
start, min_len = -1, float('inf')
i = 0
while i < m:
if S[i] == T[0]:
j = i; k = 0
while j < m and k < n:
if S[j] == T[k]:
k += 1
j += 1
if k == n:
end = j-1
k = n-1
while k >= 0:
if S[j-1] == T[k]:
k -= 1
j -= 1
i = j
if end - j + 1 < min_len:
min_len = end - j + 1; start = j
i += 1
return "" if start==-1 else S[start:start+min_len]
# 94. Regular Expression Matching (#10)
def isMatchRegex(s, p):
m, n = len(s), len(p)
dp = [[False]*(n+1) for _ in range(m+1)]
dp[0][0] = True
for j in range(2, n+1):
if p[j-1] == '*':
dp[0][j] = dp[0][j-2]
for i in range(1, m+1):
for j in range(1, n+1):
if p[j-1] in {s[i-1], '.'}:
dp[i][j] = dp[i-1][j-1]
elif p[j-1] == '*':
dp[i][j] = dp[i][j-2] or (p[j-2] in {s[i-1], '.'} and dp[i-1][j])
return dp[m][n]
# 95. Merge k Sorted Lists (#23)
class ListNode:
def __init__(self, val=0, next=None):
self.val = val; self.next = next
def mergeKLists(lists):
heap = []
for i, node in enumerate(lists):
if node:
heapq.heappush(heap, (node.val, i, node))
dummy = ListNode()
cur = dummy
while heap:
val, i, node = heapq.heappop(heap)
cur.next = node; cur = node
if node.next:
heapq.heappush(heap, (node.next.val, i, node.next))
return dummy.next
# 96. Word Ladder II (#126)
def findLadders(beginWord, endWord, wordList):
wordSet = set(wordList); wordSet.add(beginWord)
layer = {beginWord: [[beginWord]]}
while layer and endWord not in layer:
next_layer = collections.defaultdict(list)
for word, paths in layer.items():
for i in range(len(word)):
for ch in 'abcdefghijklmnopqrstuvwxyz':
new = word[:i]+ch+word[i+1:]
if new in wordSet:
next_layer[new] += [path+[new] for path in paths]
wordSet -= set(next_layer.keys())
layer = next_layer
return layer.get(endWord, [])
# 97. Max Sum Rectangle in 2D Matrix (#363 handled above) – already solved
# 98. Largest Rectangle in Histogram (#84)
def largestRectangleArea(heights):
stack = [-1]; best = 0
for i, h in enumerate(heights + [0]):
while heights[stack[-1]] > h:
H = heights[stack.pop()]
best = max(best, H * (i - stack[-1] - 1))
stack.append(i)
return best
# 99. Subarrays with K Different Integers (#992)
def subarraysWithKDistinct(nums, k):
def atMost(k):
freq = collections.Counter(); l = res = 0
for r, x in enumerate(nums):
freq[x] += 1
while len(freq) > k:
freq[nums[l]] -= 1
if freq[nums[l]] == 0: del freq[nums[l]]
l += 1
res += r - l + 1
return res
return atMost(k) - atMost(k-1)
# 100. Swim in Rising Water (#778)
def swimInWater(grid):
n = len(grid)
lo, hi = 0, n*n-1
dirs = [(1,0),(-1,0),(0,1),(0,-1)]
def feasible(T):
if grid[0][0] > T: return False
stack = [(0,0)]
seen = {(0,0)}
while stack:
r,c = stack.pop()
if (r,c) == (n-1,n-1): return True
for dr,dc in dirs:
nr,nc = r+dr,c+dc
if 0<=nr<n and 0<=nc<n and (nr,nc) not in seen and grid[nr][nc]<=T:
seen.add((nr,nc)); stack.append((nr,nc))
return False
while lo < hi:
mid = (lo+hi)//2
if feasible(mid):
hi = mid
else:
lo = mid+1
return lo