0% found this document useful (0 votes)
6 views20 pages

100 Questions

The document contains a collection of coding problems categorized by difficulty (Easy and Medium) along with their respective solutions in Python. Each problem is identified by an ID, title, platform, difficulty, and topic, with solutions designed to run efficiently. The document serves as a reference for algorithmic challenges and their implementations.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views20 pages

100 Questions

The document contains a collection of coding problems categorized by difficulty (Easy and Medium) along with their respective solutions in Python. Each problem is identified by an ID, title, platform, difficulty, and topic, with solutions designed to run efficiently. The document serves as a reference for algorithmic challenges and their implementations.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

"""

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

You might also like