if (len(curr_can) <= (4 - len(curr_ip)) * 3) and (len(curr_can) >= 4 - len(curr_ip)): find_ip(curr_ip + [curr_can[0]], curr_can[1:]) if (curr_can[0] != '0') and (len(curr_can) >= 2): find_ip(curr_ip + [curr_can[:2]], curr_can[2:]) iflen(curr_can) >= 3andint(curr_can[:3]) <= 255: find_ip(curr_ip + [curr_can[:3]], curr_can[3:]) new_s = '' for i in s: if i.isdigit(): new_s = ''.join([new_s, i])
find_ip([], new_s) return results
Dynamic Programming
53 Easy
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defmaxSubArray(self, nums: List[int]) -> int: curr_max = nums[0] prev_sum = nums[0] # find the largest sum end with nums[i] for i inrange(1, len(nums)): # if f[i - 1] + f[i] > f(i) then largest sum end with f[i] is f[i - 1] + f[i] else f[i] # in this case, it is same as max(f[i - 1] + f[i], f[i]) curr_sum = max(nums[i], prev_sum + nums[i]) prev_sum = curr_sum if curr_sum > curr_max: curr_max = curr_sum return curr_max
70 Easy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defclimbStairs(self, n: int) -> int: if n == 1: return1
classSolution: defmaxProfit(self, prices: List[int]) -> int: # f(n) = max profit if sell at day n # diff(n, n - 1) = prices[n] - price[n - 1] # f(n) = max(f(n - 1) + diff(n, n - 1), diff(n, n - 1))
curr_max = 0 prev_profit = 0 for i inrange(1, len(prices)): diff = prices[i] - prices[i - 1] curr_profit = max(prev_profit + diff, diff) if curr_profit > curr_max: curr_max = curr_profit
prev_profit = curr_profit return curr_max
122 Easy
1 2 3 4 5 6 7 8 9 10
classSolution: defmaxProfit(self, prices: List[int]) -> int: # f(n) = sum of positive gain til end of day n # f(n) = f(n - 1) + max(0, profit) curr_sum = 0 for i inrange(1, len(prices)): profit = prices[i] - prices[i - 1] curr_sum = max(0, profit) + curr_sum return curr_sum
118 Easy
1 2 3 4 5 6 7 8
classSolution: defgenerate(self, numRows: int) -> List[List[int]]: out = [[1]] for i inrange(1, numRows): curr_row = [1] + [out[i - 1][j - 1] + out[i - 1][j] for j inrange(1, len(out[i - 1]))] + [1] out.append(curr_row) return out
classSolution: deflongestPalindrome(self, s: str) -> str: # f(i, j): 1 if i -> j is a palindromic substring # f(i, i): 1 # f(i, i + 1): 1 if i -> i+1 is a palindromic substring # f(i, j): 1 if s[i] == s[j] and f[i+1 : j-1] else 0
dp = [[0] * len(s) for _ inrange(len(s))] level = 1 out_str = s[0] iflen(s) == 1: return s for i inrange(len(s)): dp[i][i] = 1
while level < len(s): for j inrange(len(s) - level): if s[j] == s[j + level]: l = j + 1 r = j + level - 1 if (level == 1) or (dp[l][r]): dp[j][j + level] = 1 out_str = s[j:j + level + 1]
level += 1 return out_str
55 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defcanJump(self, nums: List[int]) -> bool: # f(n): if we can get from n -> nums[-1] # f(-1): True # f(n): True if any([f(n) for i in range(n)]) dp = [False] * len(nums) dp[-1] = True for i inrange(len(nums) - 2, -1, -1): for j inrange(min(nums[i], len(nums) - i) + 1): if dp[j + i]: dp[i] = True break return dp[0]
64 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defminPathSum(self, grid: List[List[int]]) -> int: # f(i, j) = min sum at position (i, j) # f(0, 1:) = f(0, j) + f(0, j - 1) # f(1:, 0) = f(i, 0) + f(i - 1, 0) # f(i, j) = min(f(i - 1, j), f(i, j - 1)) + grid[i][j] m, n = len(grid), len(grid[0]) for i inrange(1, n): grid[0][i] = grid[0][i] + grid[0][i - 1] for i inrange(1, m): grid[i][0] = grid[i][0] + grid[i - 1][0] for i inrange(1, m): for j inrange(1, n): grid[i][j] = min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j] return grid[-1][-1]
classSolution: defuniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: # the key is to set 1 to 0 and initialization m, n = len(obstacleGrid), len(obstacleGrid[0]) assign_num = 1 if obstacleGrid[0][0] == 1: return0
for i inrange(n): if obstacleGrid[0][i] == 1: obstacleGrid[0][i] = 0 assign_num = 0 else: obstacleGrid[0][i] = assign_num assign_num = 1 for i inrange(1, m): if obstacleGrid[i][0] == 1: obstacleGrid[i][0] = 0 assign_num = 0 else: obstacleGrid[i][0] = assign_num for i inrange(1, m): for j inrange(1, n): if obstacleGrid[i][j] == 1: obstacleGrid[i][j] = 0 else: obstacleGrid[i][j] = obstacleGrid[i - 1][j] + obstacleGrid[i][j - 1] return obstacleGrid[-1][-1]
120 Medium
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: defminimumTotal(self, triangle: List[List[int]]) -> int: # f(n, i): Minimum distance to layer n, position i # f(len(triangle), :) = triangle[-1] # f(n, i) = min(f(n + 1, i), f(n + 1, i + 1)) + triangle[n][i]
depth = len(triangle) for n inrange(depth - 2, -1, -1): for i inrange(len(triangle[n])): triangle[n][i] = min(triangle[n + 1][i], triangle[n + 1][i + 1]) + triangle[n][i] return triangle[0][0]
classSolution: defintegerBreak(self, n: int) -> int: # f(n): max mul # f(2): 1 # f(3): 2 # f(n): f(i) * f(j) where i != j if n == 2: return1 if n == 3: return2
dp = [i for i inrange(n + 1)] for i inrange(4, n + 1): l, r = 2, i - 2 while l <= r: curr_prod = dp[l] * dp[r] if curr_prod > dp[i]: dp[i] = curr_prod
l += 1 r -= 1 return dp[-1]
300 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: deflengthOfLIS(self, nums: List[int]) -> int: # f(n): max strictly increasing sub sequence ending with n # f(0): 1 # f(n): dp = [1] * len(nums) curr_max = 1 for i inrange(1, len(nums)): vals = [] for j inrange(i, -1, -1): if nums[i] > nums[j]: vals.append(dp[j])
classSolution: defnumSquares(self, n: int) -> int: dp = [0] * (n + 1) vals = [] for i inrange(1, n + 1): if i ** 2 <= n: dp[i ** 2] = 1 else: break
vals.append(i ** 2)
for i inrange(2, len(dp)): curr_min = i if i notin vals: j = 0 while (j < len(vals)) and (vals[j] <= i): curr_counts = 1 + dp[i - vals[j]] if curr_counts < curr_min: curr_min = curr_counts j += 1 dp[i] = curr_min return dp[-1]
1143 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: deflongestCommonSubsequence(self, text1: str, text2: str) -> int: # f(i, j): largest number of substring match text1[:i], text2[:j] # If text1[i] != text2[j], f(i, j) = max(f(i, j - 1), f(i - 1, j)) # If text1[i] == text2[j], f(i, j) = f(i - 1, j - 1) + 1 M, N = len(text1), len(text2) dp = [[0] * (N + 1) for _ inrange(M + 1)] for i inrange(1, M + 1): for j inrange(1, N + 1): if text1[i - 1] == text2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) return dp[M][N]
494 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: deffindTargetSumWays(self, nums: List[int], S: int) -> int: sumAll = sum(nums) if S > sumAll or (S + sumAll) % 2: return0 target = (S + sumAll) // 2
dp = [0] * (target + 1) dp[0] = 1
for num in nums: for j inrange(target, num - 1, -1): dp[j] = dp[j] + dp[j - num] return dp[-1]
152 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defmaxProduct(self, nums: List[int]) -> int: # f(i): max product at i # min_prod: current min product # max_prod: current max product # f(i): max(f(i - 1), max_prod) min_prod = nums[0] max_prod = nums[0] for i inrange(1, len(nums)): temp = min_prod min_prod = min(min_prod * nums[i], nums[i], max_prod * nums[i]) max_prod = max(temp * nums[i], nums[i], max_prod * nums[i]) nums[i] = max(nums[i - 1], max_prod)
return nums[-1]
518 Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defchange(self, amount: int, coins: List[int]) -> int: n, m = len(coins), amount + 1 dp = [1] * m for i inrange(1, m): if i % coins[0] != 0: dp[i] = 0 for i inrange(1, n): for j inrange(1, m): if coins[i] <= j: dp[j] = dp[j - coins[i]] + dp[j]
dp = [[0] * (target + 1) for _ inrange(target + 1)] dp[0][0] = 1 out = 0 for i inrange(1, target + 1): for j inrange(1, target + 1): for num in nums: if num <= j: dp[i][j] += dp[i - 1][j - num] out += dp[i][j]
classSolution: defcanPartition(self, nums: List[int]) -> bool: # f(i, j): whether we can form num ber j with nums[:i] items # 0/1 knapsack problem. num_sum = sum(nums) if num_sum % 2 != 0: returnFalse target = num_sum // 2 dp = [True] + [False] * (target) if nums[0] <= (target): dp[nums[0]] = True for i inrange(1, len(nums)): # right to left in order to avoid overrdie of dp[j - nums[i]] for j inrange(target, -1, -1): if nums[i] <= j: dp[j] = dp[j - nums[i]] or dp[j]
# 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 classSolution: defrob(self, root: TreeNode) -> int:
# do not rob this node, we can rob root.left and root.right val_1 = max(left_node[0], left_node[1]) + max(right_node[0], right_node[1]) # rob this node, this implies that we cannot rob root.left or root.right val_2 = left_node[0] + right_node[0] + node.val