classSolution: deflemonadeChange(self, bills: List[int]) -> bool: five = ten = 0 for num in bills: if num == 5: five += 1 elif num == 10and five: ten += 1 five -= 1 elif num == 20and five and ten: five -= 1 ten -= 1 elif num == 20and five >= 3: five -= 3 else: returnFalse returnTrue
122. 买卖股票的最佳时机 II (2021.2.20)
自己的答案
1 2 3 4 5 6 7 8
classSolution: defmaxProfit(self, prices: List[int]) -> int: sum = 0 for i inrange(len(prices)-1): gain = prices[i+1] - prices[i] if gain > 0: sum += gain returnsum
优秀代码
1 2 3 4
classSolution: defmaxProfit(self, prices: List[int]) -> int: returnsum(max(prices[i + 1] - prices[i], 0) for i inrange(len(prices) - 1)) returnsum([b-a for a,b inzip(prices,prices[1:]) if b-a > 0])
classSolution: defcanJump(self, nums: List[int]) -> bool: cover = 0 for i, r inenumerate(nums): if i > cover: returnFalse cover = max(cover, i+nums[i]) if cover >= len(nums)-1: break returnTrue
二分查找
目标函数单调性(单调递增或者递减)
存在上下界
能够通过索引访问
69. x 的平方根 (2021.2.22)
自己的答案
1 2 3 4 5 6 7 8 9 10 11
classSolution: defmySqrt(self, x: int) -> int: left, right = 0, x while left <= right: mid = (left + right)//2 if mid * mid <= x < (mid+1)*(mid+1): return mid if mid *mid > x: right = mid - 1 else: left = mid + 1
优秀代码
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defmySqrt(self, x: int) -> int: left, right = 0, x while left <= right: mid = left + (right - left) // 2 mid_square = mid ** 2 if mid_square == x: return mid elif mid_square > x: right = mid - 1 else: left = mid + 1 return right
classSolution: defmySqrt(self, x: int) -> int: result = x while result**2 > x: result = (result + x//result)//2 return result
33. 搜索旋转排序数组 (2021.2.25)
自己的答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defsearch(self, nums: List[int], target: int) -> int: left, right = 0, len(nums)-1 while left <= right: mid = left + (right - left)//2 if nums[mid] == target: return mid if nums[mid] >= nums[left]: if (nums[left] <= target) and (target < nums[mid]): right = mid - 1 else: left += 1 else: if (nums[mid] < target) and (target <= nums[right]): left = mid +1 else: right -= 1 return -1
def__init__(self): """ Initialize your data structure here. """ self.root = {} self.end = "#"
definsert(self, word: str) -> None: """ Inserts a word into the trie. """ node = self.root for i in word: node = node.setdefault(i, {}) node[self.end] = self.end
defsearch(self, word: str) -> bool: """ Returns if the word is in the trie. """ node = self.root for i in word: if i notin node: returnFalse node = node[i] return self.end in node
defstartsWith(self, prefix: str) -> bool: """ Returns if there is any word in the trie that starts with the given prefix. """ node = self.root for i in prefix: if i notin node: returnFalse node = node[i] returnTrue
# 构建Trie root = collections.defaultdict() for word in words: node = root for char in word: node = node.setdefault(char, collections.defaultdict()) node[self.end] = self.end
for i inrange(len(board)): for j inrange(len(board[0])): if board[i][j] in root: self._dfs(board, i, j, '', root) returnlist(self.result)
# 深度优先搜索 def_dfs(self, board, i, j, curchar, curdict): curchar = curchar + board[i][j] curdict = curdict[board[i][j]] if self.end in curdict: self.result.add(curchar) tmp, board[i][j] = board[i][j], "@" for ori inrange(4): x = i + self.dx[ori] y = j + self.dy[ori] if0<=x<len(board) and0<=y<len(board[0]) and board[x][y] != "@"and board[x][y] in curdict: self._dfs(board, x, y, curchar, curdict) board[i][j] = tmp
defmerge(arr, left, mid, right): temp = [0]*(right-left+1) i, j, k = left, mid+1, 0
while (i<=mid) and (j<=right): if arr[i] <= arr[j]: temp[k] = arr[i] i += 1 else: temp[k] = arr[j] j += 1 k += 1 while i<=mid: temp[k] = arr[i] k+=1; i+=1 while j<=right: temp[k] = arr[j] k+=1; j+=1 for p inrange(k): arr[left+p] = temp[p]
# while '()' in s or '{}' in s or '[]' in s: # s = s.replace('()','').replace('{}','').replace('[]','') # if s == '': # return True # else: # return False
stack = [] dic = {')':'(', '}':'{', ']':'['} for i in s: if i in dic: ifnot stack or stack.pop() != dic[i]: returnFalse else: stack.append(i) returnnot stack
for i inrange(0, len(heights)): while heights[i] < heights[stack[-1]]: h = heights[stack.pop()] w = i - stack[-1] - 1 res = max(res, h*w) stack.append(i) return res
239. 滑动窗口最大值 (2021.6.3)
技巧:使用双端队列(队列的第一个元素始终保持最大)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defmaxSlidingWindow(self, nums: List[int], k: int) -> List[int]: res = [] d = collections.deque()
for i, num inenumerate(nums): while d and num > nums[d[-1]]: d.pop() d.append(i) if i - k == d[0]: d.popleft() if i >= k-1: res.append(nums[d[0]]) return res
def__init__(self, k: int): """ Initialize your data structure here. Set the size of the deque to be k. """ self.deque = [-1]*k self.head, self.tail = 0, 0 self.size = 0 self.cap = k
definsertFront(self, value: int) -> bool: """ Adds an item at the front of Deque. Return true if the operation is successful. """ if self.isFull(): returnFalse if self.isEmpty(): self.deque[self.head] = value else: self.head = (self.head - 1) % self.cap self.deque[self.head] = value self.size += 1 returnTrue
definsertLast(self, value: int) -> bool: """ Adds an item at the rear of Deque. Return true if the operation is successful. """ if self.isFull(): returnFalse if self.isEmpty(): self.deque[self.tail] = value else: self.tail = (self.tail + 1) % self.cap self.deque[self.tail] = value self.size += 1 returnTrue
defdeleteFront(self) -> bool: """ Deletes an item from the front of Deque. Return true if the operation is successful. """ if self.isEmpty(): returnFalse self.deque[self.head] = -1 self.head = (self.head + 1) % self.cap self.size -= 1 if self.isEmpty(): self.tail = self.head returnTrue
defdeleteLast(self) -> bool: """ Deletes an item from the rear of Deque. Return true if the operation is successful. """ if self.isEmpty(): returnFalse self.deque[self.tail] = -1 self.tail = (self.tail - 1) % self.cap self.size -= 1 if self.isEmpty(): self.head = self.tail returnTrue
defgetFront(self) -> int: """ Get the front item from the deque. """ return self.deque[self.head]
defgetRear(self) -> int: """ Get the last item from the deque. """ return self.deque[self.tail]
defisEmpty(self) -> bool: """ Checks whether the circular deque is empty or not. """ if self.size == 0: returnTrue
defisFull(self) -> bool: """ Checks whether the circular deque is full or not. """ if self.size == self.cap: returnTrue
classSolution: deftrap(self, height: List[int]) -> int: 1. 暴力法 # res = 0 # for i in range(len(height)): # left, right = 0, 0 # for j in range(0, i): # left = max(left, height[j]) # for k in range(i+1, len(height)): # right = max(right, height[k]) # if min(left, right) - height[i] < 0: # res += 0 # else: # res += min(left, right) - height[i] # return res
2. 单调栈 # stack = [] # res = 0
# for i in range(len(height)): # while stack and height[i] > height[stack[-1]]: # temp = stack.pop() # if not stack: # break # h = min(height[i], height[stack[-1]]) - height[temp] # w = i - stack[-1] - 1 # res += h * w # stack.append(i) # return res
3. 双指针 left, right = 0, len(height) - 1 max_left, max_right, res = 0, 0, 0 while left < right: if height[left] <= height[right]: if height[left] > max_left: max_left = height[left] else: res += max_left - height[left] left += 1 else: if height[right] > max_right: max_right = height[right] else: res += max_right - height[right] right -= 1 return res
""" # Definition for a Node. class Node: def __init__(self, val=None, children=None): self.val = val self.children = children """
classSolution: deflevelOrder(self, root: 'Node') -> List[List[int]]: result = [] defrecursion(root, level): iflen(result) == level: result.append([]) result[level].append(root.val) for child in root.children: recursion(child, level + 1)
if root != None: recursion(root, 0) return result
泛型递归、树的递归
70. 爬楼梯 (2021.6.4)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from functools import lru_cache classSolution: @lru_cache() defclimbStairs(self, n: int) -> int: if n <= 2: return n return self.climbStairs(n - 1) + self.climbStairs(n - 2)
# if n <= 2: # return n # f1, f2 = 0, 1 # for i in range(n): # f1, f2 = f2, f1 + f2 # return f2
22. 括号生成 (2021.6.4)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defgenerateParenthesis(self, n: int) -> List[str]: left, right = 0, 0 res = [] defrecursion(left, right, s): if left == n and right == n: res.append(s) if left < n: recursion(left + 1, right, s + "(") if right < left: recursion(left, right + 1, s + ")") recursion(left, right, '') return res
# 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: defisValidBST(self, root: TreeNode) -> bool: # def recursion(root, left, right): # if not root: # return True # if root.val <= left or root.val >= right: # return False # return recursion(root.left, left, root.val) and recursion(root.right, root.val, right) # return recursion(root, -inf, inf)
ifnot root: returnTrue stack = [(root, -inf, inf)] while stack: root, left, right = stack.pop() if root.val <= left or root.val >= right: returnFalse if root.left: stack.append((root.left, left, root.val)) if root.right: stack.append((root.right, root.val, right)) returnTrue
104. 二叉树的最大深度 (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13
# 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: defmaxDepth(self, root: TreeNode) -> int: ifnot root: return0 left = self.maxDepth(root.left) right = self.maxDepth(root.right) returnmax(left, right) + 1
111. 二叉树的最小深度 (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# 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: defminDepth(self, root: TreeNode) -> int: ifnot root: return0 left = self.minDepth(root.left) right = self.minDepth(root.right) ifnot root.left ornot root.right: return left + right + 1 else: returnmin(left, right) + 1
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None
classCodec:
defserialize(self, root): """Encodes a tree to a single string. :type root: TreeNode :rtype: str """ defrecursion(root): if root: res.append(str(root.val)) recursion(root.left) recursion(root.right) else: res.append('#') res = [] recursion(root) return" ".join(res)
defdeserialize(self, data): """Decodes your encoded data to tree. :type data: str :rtype: TreeNode """ defrecursion(): val = next(vals) if val == '#': returnNone Node = TreeNode(int(val)) Node.left = recursion() Node.right = recursion() return Node vals = iter(data.split()) return recursion()
# Your Codec object will be instantiated and called as such: # ser = Codec() # deser = Codec() # ans = deser.deserialize(ser.serialize(root))
236. 二叉树的最近公共祖先 (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None
classSolution: deflowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': ifnot root or root == p or root == q: return root left = self.lowestCommonAncestor(root.left, p, q) right = self.lowestCommonAncestor(root.right, p, q) ifnot left: return right ifnot right: return left return root
105. 从前序与中序遍历序列构造二叉树 (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# 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: defbuildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: if inorder: ind = inorder.index(preorder.pop(0)) root = TreeNode(inorder[ind]) root.left = self.buildTree(preorder, inorder[0:ind]) root.right = self.buildTree(preorder, inorder[ind+1:]) return root
77. 组合 (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defcombine(self, n: int, k: int) -> List[List[int]]: res, stack = [], [] x = 1 whileTrue: l = len(stack) if l == k: res.append(stack[:]) if l == k or x > n - k + l + 1: ifnot stack: return res x = stack.pop() + 1 else: stack.append(x) x += 1
46. 全排列 (2021.6.8)
1 2 3 4 5 6 7 8 9 10
classSolution: defpermute(self, nums: List[int]) -> List[List[int]]: res = [] defdfs(nums, path, res): ifnot nums: res.append(path) for i inrange(len(nums)): dfs(nums[:i]+nums[i+1:], path+[nums[i]], res) dfs(nums, [], res) return res
47. 全排列 II (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defpermuteUnique(self, nums: List[int]) -> List[List[int]]: res, visited = [], [] defdfs(nums, path, res): ifnot nums: res.append(path) for i inrange(len(nums)): if i > 0and nums[i] == nums[i-1]: continue dfs(nums[:i]+nums[i+1:], path+[nums[i]], res) nums.sort() dfs(nums, [], res) return res
分治、回溯
50. Pow(x, n) (2021.6.8)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defmyPow(self, x: float, n: int) -> float: if n == 0: return1 if n < 0: x, n = 1/x, -n
defrecursion(x, n): if n == 1: return x val = recursion(x, n//2) if n % 2 == 0: return val * val else: return val * val * x
return recursion(x, n)
78. 子集 (2021.6.9)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: defsubsets(self, nums: List[int]) -> List[List[int]]: # res = [[]] # for i in nums: # res = res + [ x + [i] for x in res] # return res
res = [] defdfs(index, val, nums): if index == len(nums): res.append(val) returnNone dfs(index+1, val.copy(), nums) val.append(nums[index]) dfs(index+1, val.copy(), nums) dfs(0, [], nums) return res
defrecursion(lo, hi): if lo == hi: return nums[lo]
mid= (lo + hi)//2 left = recursion(lo, mid) right = recursion(mid+1, hi) if left == right: return left left_count = sum([1for num in nums[lo:hi+1] if num == left]) right_count = sum([1for num in nums[lo:hi+1] if num == right]) if left_count > right_count: return left else: return right
defrecursion(index, digits, s): if index == len(digits): res.append(s) returnNone for i in hash_map[digits[index]]: recursion(index+1, digits, s+i) recursion(0, digits, '') return res
51. N 皇后 (2021.6.9)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defsolveNQueens(self, n: int) -> List[List[str]]: res = [] defrecursion(queens, pie, na): row = len(queens) if row == n: res.append(queens) returnNone for col inrange(n): if col notin queens and row+col notin pie and row-col notin na: recursion(queens+[col], pie+[row+col], na+[row-col]) recursion([], [], []) res_form = [['.'*i + 'Q' + '.'*(n-i-1) for i in r] for r in res] return res_form
# 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: deflevelOrder(self, root: TreeNode) -> List[List[int]]: # res = [] # def dfs(level, root): # if not root: # return None # if level == len(res): # res.append([]) # res[level].append(root.val) # dfs(level + 1, root.left) # dfs(level + 1, root.right) # dfs(0, root) # return res
q, res = collections.deque(), [] if root: q.append(root) whilelen(q): level = [] for _ inrange(len(q)): root = q.popleft() level.append(root.val) if root.left: q.append(root.left) if root.right: q.append(root.right) res.append(level) return res
433. 最小基因变化 (2021.6.9)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defminMutation(self, start: str, end: str, bank: List[str]) -> int: bank = set(bank) q = collections.deque([(start, 0)]) while q: start, res = q.popleft() if start == end: return res for i inrange(8): for j in"ACGT": new = start[:i] + j + start[i+1:] if new in bank: q.append((new, res+1)) bank.discard(new) return -1
# 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: deflargestValues(self, root: TreeNode) -> List[int]: res, q = [], deque() if root: q.append(root) while q: length, level = len(q), [] for _ inrange(length): root = q.popleft() level.append(root.val) if root.left: q.append(root.left) if root.right: q.append(root.right) res.append(max(level)) return res
classSolution: defladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: wordList = set(wordList) if beginWord in wordList: wordList.remove(beginWord) if endWord notin wordList: return0
q = collections.deque([(beginWord, 1)]) length = len(beginWord) while q: begin, res = q.popleft() if begin == endWord: return res for i inrange(length): for j in string.ascii_lowercase: tmp = begin[:i] + j + begin[i+1:] if tmp in wordList: q.append((tmp, res+1)) wordList.remove(tmp) return0
classSolution: deffindLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]: wordList = set(wordList) if beginWord in wordList: wordList.remove(beginWord) if endWord notin wordList: return []
layer = {} layer[beginWord] = [[beginWord]] length = len(beginWord) while layer: newLayer = collections.defaultdict(list) for word in layer: if word == endWord: return layer[word] for i inrange(length): for j in string.ascii_lowercase: newWord = word[:i] + j + word[i+1:] if newWord in wordList: newLayer[newWord] += [x+[newWord] for x in layer[word]] wordList -= set(newLayer.keys()) layer = newLayer
# def dfs(row, col): # if grid[row][col] == "0": # return None # grid[row][col] = '0' # for index in range(4): # x = row + dx[index] # y = col + dy[index] # if 0 <= x and x <= l1-1 and y >= 0 and y <= l2-1: # dfs(x, y)
defdfs(row, col): if row < 0or col < 0or row >= l1 or col >= l2 or grid[row][col] == '0': returnNone grid[row][col] = '0' dfs(row+1, col) dfs(row-1, col) dfs(row, col+1) dfs(row, col-1)
for i inrange(l1): for j inrange(l2): if grid[i][j] == '1': dfs(i, j) count += 1 return count
classSolution: defupdateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]: d = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)] m, n = len(board), len(board[0])
defdfs(board, row, col): if row < 0or row >= m or col < 0or col >= n: returnNone if board[row][col] == 'M': board[row][col] = 'X' elif board[row][col] == 'E': count = sum(board[row+i][col+j] == 'M'for i, j in d if0 <= row+i < m and0 <= col+j < n) if count: board[row][col] = str(count) else: board[row][col] = 'B' for i, j in d: dfs(board, row+i, col+j)
dfs(board, *click) return board
贪心算法
860. 柠檬水找零 (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: deflemonadeChange(self, bills: List[int]) -> bool: five, ten = 0, 0 for i in bills: if i == 5: five += 1 elif i == 10and five: five -= 1 ten += 1 elif i == 20and five and ten: five -= 1 ten -= 1 elif i == 20and five >= 3: five -= 3 else: returnFalse returnTrue
122. 买卖股票的最佳时机 II (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defmaxProfit(self, prices: List[int]) -> int: # dp = [[0, 0] for i in range(len(prices))] # dp[0][0], dp[0][1] = 0, -prices[0] # for i in range(1, len(prices)): # dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i]) # dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]) # return dp[-1][0]
res = 0 for i inrange(1, len(prices)): if prices[i] > prices[i-1]: res += prices[i] - prices[i-1] return res
455. 分发饼干 (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: deffindContentChildren(self, g: List[int], s: List[int]) -> int: res, i, j = 0, 0, 0 g.sort() s.sort() while i < len(g) and j < len(s): if g[i] <= s[j]: res += 1 i += 1 j += 1 else: j += 1 return res
874. 模拟行走机器人 (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defrobotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: i = j = res = index = 0 d = [(0, 1), (-1, 0), (0, -1), (1, 0)] obstacles = set(map(tuple, obstacles)) for command in commands: if command == -2: index = (index + 1) % 4 elif command == -1: index = (index - 1) % 4 else: dx, dy = d[index] while command and (i + dx, j + dy) notin obstacles: i += dx j += dy command -= 1 res = max(res, i**2 + j**2)
return res
55. 跳跃游戏 (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defcanJump(self, nums: List[int]) -> bool: # end = len(nums) - 1 # for i in range(len(nums)-1, -1, -1): # if nums[i] + i >= end: # end = i # return end == 0
cover = 0 for i inrange(len(nums)): if i > cover: returnFalse cover = max(cover, i + nums[i]) if cover >= len(nums): break returnTrue
45. 跳跃游戏 II (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11
classSolution: defjump(self, nums: List[int]) -> int: iflen(nums) <= 1: return0 l, r = 0, nums[0] count = 1 while r < len(nums) - 1: count += 1 nxt = max(i + nums[i] for i inrange(l, r + 1)) l, r = r, nxt return count
二分查找
69. x 的平方根 (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defmySqrt(self, x: int) -> int: # res = x # while res ** 2 > x: # res = (res + x//res)//2 # return res
left, right = 0, x while left <= right: mid = left + (right - left)//2 x_ = mid ** 2 if x_ == x: return mid if mid ** 2 > x: right = mid - 1 else: left = mid + 1 return right
367. 有效的完全平方数 (2021.6.10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defisPerfectSquare(self, num: int) -> bool: if num <= 1: returnTrue left, right = 0, num//2 while left <= right: mid = (left + right) // 2 x = mid ** 2 if x == num: returnTrue if x > num: right = mid - 1 else: left = mid + 1 returnFalse
classSolution: defsearch(self, nums: List[int], target: int) -> int: # lo, hi = 0, len(nums) - 1 # while lo < hi: # mid = (lo + hi) // 2 # if (nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid]): # lo = mid + 1 # else: # hi = mid # # return lo if target in nums[lo:lo+1] else -1 # return lo if target == nums[lo] else -1
left, right = 0, len(nums) - 1 while left <= right: mid = (left + right) // 2 if target == nums[mid]: return mid if nums[left] <= nums[mid]: if nums[left] <= target and target < nums[mid]: right = mid - 1 else: left += 1 else: if nums[mid] < target and target <= nums[right]: left = mid + 1 else: right -= 1 return -1
def__init__(self): """ Initialize your data structure here. """ self.root = {} self.end = "#"
definsert(self, word: str) -> None: """ Inserts a word into the trie. """ node = self.root for char in word: node = node.setdefault(char, {}) node[self.end] = self.end
defsearch(self, word: str) -> bool: """ Returns if the word is in the trie. """ node = self.root for char in word: if char notin node: returnFalse node = node[char] return self.end in node
defstartsWith(self, prefix: str) -> bool: """ Returns if there is any word in the trie that starts with the given prefix. """ node = self.root for char in prefix: if char notin node: returnFalse node = node[char] returnTrue
# Your Trie object will be instantiated and called as such: # obj = Trie() # obj.insert(word) # param_2 = obj.search(word) # param_3 = obj.startsWith(prefix)
classSolution: deffindWords(self, board: List[List[str]], words: List[str]) -> List[str]: dx = [0, 0, 1, -1] dy = [1, -1, 0, 0] m, n = len(board), len(board[0]) res = set()
root = {} for word in words: node = root for char in word: node = node.setdefault(char, {}) node["#"] = True
defdfs(i, j, s, node, visited): if"#"in node: res.add(s) for d inrange(4): x = i + dx[d] y = j + dy[d] if0 <= x < m and0 <= y < n and (x, y) notin visited and board[x][y] in node: dfs(x, y, s + board[x][y], node[board[x][y]], visited | {(x, y)})
for i inrange(m): for j inrange(n): if board[i][j] in root: dfs(i, j, board[i][j], root[board[i][j]], {(i, j)}) returnlist(res)
defparent(k): root = k while p[root] != root: root = p[root] while p[k] != k: tmp = k k = p[k] p[tmp] = root return root
l = len(isConnected) p = [n for n inrange(l)] for i inrange(l): for j inrange(l): if isConnected[i][j] == 1: union(i, j) returnlen(set([parent(n) for n inrange(l)]))
for i inrange(row): for j inrange(col): if grid[i][j] == '0': continue index = i * col + j if j < col - 1and grid[i][j+1] == '1': union(index, index+1) if i < row - 1and grid[i+1][j] == '1': union(index, index+col) return self.count
for i inrange(row): for j inrange(col): if board[i][j] == 'O': if i == 0or j == 0or i == row-1or j == col-1: union(i*col+j, dummy) else: for dx, dy in [(0,1), (0,-1), (1,0), (-1,0)]: if board[i+dx][j+dy] == 'O': union(i*col+j, (i+dx)*col+(j+dy)) for i inrange(row): for j inrange(col): if parent(i*col+j) == parent(dummy): board[i][j] = "O" else: board[i][j] = "X" return board
classSolution: defisValidSudoku(self, board: List[List[str]]) -> bool: # return 1 == max(list(collections.Counter( # x # for i, row in enumerate(board) # for j, c in enumerate(row) # if c != '.' # for x in ((c, i), (j, c), ((i//3)*3 + j//3, c, "#")) # ).values())+ [1])
row = [{} for _ inrange(9)] col = [{} for _ inrange(9)] block = [{} for _ inrange(9)]
for i inrange(9): for j inrange(9): if board[i][j] != '.': num = board[i][j] row[i][num] = row[i].get(num, 0) + 1 col[j][num] = col[j].get(num, 0) + 1 block[(i//3)*3+j//3][num] = block[(i//3)*3+j//3].get(num, 0) + 1
classSolution: defsolveSudoku(self, board: List[List[str]]) -> None: """ Do not return anything, modify board in-place instead. """ row = [set(range(1, 10)) for _ inrange(9)] col = [set(range(1, 10)) for _ inrange(9)] block = [set(range(1, 10)) for _ inrange(9)]
empty = [] for i inrange(9): for j inrange(9): if board[i][j] == '.': empty.append((i, j)) else: num = board[i][j] row[i].remove(int(num)) col[j].remove(int(num)) block[(i//3)*3+j//3].remove(int(num))
defdfs(iter=0): ifiter == len(empty): returnTrue i, j = empty[iter] for num in row[i] & col[j] & block[(i//3)*3+j//3]: board[i][j] = str(num) row[i].remove(num) col[j].remove(num) block[(i//3)*3+j//3].remove(num) if dfs(iter + 1): returnTrue row[i].add(num) col[j].add(num) block[(i//3)*3+j//3].add(num) returnFalse return dfs()
classSolution: defladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: # wordList = set(wordList) # if beginWord in wordList: # wordList.remove(beginWord) # if endWord not in wordList: # return 0
# q = collections.deque([(beginWord, 1)]) # length = len(beginWord) # while q: # begin, res = q.popleft() # if begin == endWord: # return res # for i in range(length): # for j in string.ascii_lowercase: # tmp = begin[:i] + j + begin[i+1:] # if tmp in wordList: # q.append((tmp, res+1)) # wordList.remove(tmp) # return 0
if endWord notin wordList: return0 wordList = set(wordList) length = len(beginWord) res = 1
front = {beginWord} back = {endWord}
while front: res += 1 next_front = set() for word in front: for i inrange(length): for char in string.ascii_lowercase: if char != word[i]: new_word = word[:i] + char + word[i+1:] if new_word in back: return res if new_word in wordList: next_front.add(new_word) wordList.remove(new_word) front = next_front iflen(front) > len(back): front, back = back, front return0
classSolution: defminMutation(self, start: str, end: str, bank: List[str]) -> int: # bank = set(bank) # q = collections.deque([(start, 0)]) # while q: # start, res = q.popleft() # if start == end: # return res # for i in range(8): # for j in "ACGT": # new = start[:i] + j + start[i+1:] # if new in bank: # q.append((new, res+1)) # bank.discard(new) # return -1
if end notin bank: return -1 bank = set(bank) length = len(start) res = 0
front, back = {start}, {end}
while front: res += 1 next_front = set() for seq in front: for i inrange(length): for c in"ACGT": if c != seq[i]: new_seq = seq[:i] + c + seq[i+1:] if new_seq in back: return res if new_seq in bank: next_front.add(new_seq) bank.remove(new_seq) front = next_front iflen(front) > len(back): front, back = back, front return -1
classSolution: defshortestPathBinaryMatrix(self, grid: List[List[int]]) -> int: # if grid[0][0] == 1 or grid[-1][-1] == 1 or not grid: # return -1 # n = len(grid) # if n <= 2: return n # d = [(0,1), (0,-1), (-1,0), (1,0), (1,1), (1,-1), (-1,1), (-1,-1)]
# q, visited = [(0, 0, 1)], set() # while q: # next_q = [] # for i, j, r in q: # visited.add((i, j)) # if i == j == n-1: # return r # for x, y in d: # if 0<=i+x<n and 0<=j+y<n and grid[i+x][j+y]==0: # if (i+x, j+y) not in visited: # next_q.append((i+x, j+y, r+1)) # q = next_q # return -1
# if grid[0][0] == 1 or grid[-1][-1] == 1 or not grid: # return -1 # n, q = len(grid), [(0,0,2)] # if n <= 2: return n
# for i, j, r in q: # for x, y in [(i,j+1), (i,j-1), (i-1,j), (i+1,j), (i+1,j+1), (i+1,j-1), (i-1,j+1), (i-1,j-1)]: # if x == y == n-1: # return r # if 0 <= x < n and 0 <= y < n and not grid[x][y]: # q += [(x, y, r+1)] # grid[x][y] = 1 # return -1
n = len(grid) if n==0or grid[0][0]==1: return -1 target = (n-1,n-1) f0 = 2*n-2 scores = {(0,0): f0} heap = [(f0,1,0,0)] while heap: f,g,i,j = heappop(heap) if (i,j) == target: return g children = [(i+1,j),(i-1,j),(i,j+1),(i,j-1),(i+1,j+1),(i-1,j-1),(i+1,j-1),(i-1,j+1)] for k,l in children: if0 <= k < n and0 <= l <n and grid[k][l] == 0: heuristic = max(abs(k-target[0]), abs(l-target[1])) new_score = heuristic + g + 1 if new_score < scores.get((k,l), float('inf')): scores[(k,l)] = new_score heappush(heap,(new_score,g+1,k,l)) return -1
# s = ''.join([str(c) for row in board for c in row]) # q, visited, count = [s], set(), 0 # while q: # next_q = [] # for s in q: # visited.add(s) # if s == '123450': # return count # loc = s.index('0') # arr = list(s) # for i in d[loc]: # new_arr = arr[:] # new_arr[loc], new_arr[i] = new_arr[i], new_arr[loc] # new_s = ''.join(new_arr) # if new_s not in visited: # next_q.append(new_s) # q = next_q # count += 1 # return -1
d = [[1,3], [0,2,4], [1,5], [0,4], [1,3,5], [2,4]] board = board[0] + board[1] q, visited = [(tuple(board), board.index(0), 0)], set() while q: state, loc, count = q.pop(0) if state == (1,2,3,4,5,0): return count visited.add(state) for i in d[loc]: new = list(state) new[i], new[loc] = new[loc], new[i] new = tuple(new) if new notin visited: q.append((new, new.index(0), count+1)) return -1
# scores = [0]*6 # trues = {0:[1,2], # 1:[0,0], # 2:[0,1], # 3:[0,2], # 4:[1,0], # 5:[1,1]} # for num in range(6): # scores[num] = [[abs(trues[num][0]-i)+abs(trues[num][1]-j) for j in range(3)] for i in range(2)]
# def calc(new): # board = [] # new = list(new) # board.append(new[:3]) # board.append(new[3:]) # return sum([scores[board[i][j]][i][j] for i in range(2) for j in range(3)])
# d = [[1,3], [0,2,4], [1,5], [0,4], [1,3,5], [2,4]] # board = board[0] + board[1] # q, visited = [(0, tuple(board), board.index(0), 0)], set() # while q: # score, state, loc, count = heappop(q) # if state == (1,2,3,4,5,0): # return count # visited.add(state) # for i in d[loc]: # new = list(state) # new[i], new[loc] = new[loc], new[i] # new = tuple(new) # if new not in visited: # heappush(q, (calc(new)+count+1, new, new.index(0), count+1)) # return -1
位运算
191. 位1的个数 (2021.6.17)
1 2 3 4 5 6 7
classSolution: defhammingWeight(self, n: int) -> int: count = 0 while n != 0: count += 1 n &= n-1 return count
# Your LRUCache object will be instantiated and called as such: # obj = LRUCache(capacity) # param_1 = obj.get(key) # obj.put(key,value)
排序算法 (2021.6.17)
初级排序 - O(n^2)
冒泡排序
1 2 3 4 5 6 7
defbubble_sort(array): n = len(array) for i inrange(n): for j inrange(n-i-1): if array[j] > array[j+1]: array[j], array[j+1] = array[j+1], array[j] return array
插入排序
1 2 3 4 5 6 7 8 9
definsertion_sort(array): for i inrange(1, len(array)): key = array[i] j = i - 1 while j >= 0and array[j] > key: array[j+1] = array[j] j -= 1 array[j+1] = key return array
选择排序
1 2 3 4 5 6 7 8
defselection_sort(array): for i inrange(len(array)): idx = i for j inrange(i+1, len(array)): if array[idx] > array[j]: idx = j array[i], array[idx] = array[idx], array[i] return array
高级排序 - O(N*LogN)
快速排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from random import randint
defquick_sort(array): iflen(array) < 2: return array pivot = array[randint(0, len(array)-1)] low, same, high = [], [], [] for i in array: if i > pivot: high.append(i) elif i == pivot: same.append(i) else: low.append(i) return quick_sort(low) + same + quick_sort(high)
for x in arr1: freq[x] += 1 for i in arr2: ans.extend([i]*freq[i]) freq[i] = 0 for j inrange(upper + 1): if freq[j] > 0: ans.extend([j]*freq[j]) return ans
classSolution: deflengthOfLIS(self, nums: List[int]) -> int: # n = len(nums) # dp = [1]*n # for i in range(1, n): # for j in range(i): # if nums[i] > nums[j]: # dp[i] = max(dp[i], dp[j]+1) # return max(dp)
tail = [] for x in nums: ifnot tail or x > tail[-1]: tail.append(x) else: l, r = 0, len(tail)-1 while l <= r: mid = (l+r) >> 1 if tail[mid] >= x: loc = mid r = mid - 1 else: l = mid + 1 tail[loc] = x returnlen(tail)
classSolution: deflongestValidParentheses(self, s: str) -> int: # stack, res = [-1], 0 # for index, char in enumerate(s): # if char == '(': # stack.append(index) # else: # stack.pop() # if not stack: # stack.append(index) # else: # res = max(res, index - stack[-1]) # return res
n = len(s) if n == 0: return0
dp = [0]*n for i inrange(n): if s[i] == ")": pre = i- dp[i-1] -1 if pre >= 0and s[pre] == "(": dp[i] = dp[i-1] + 2 if pre > 0: dp[i] += dp[pre-1] returnmax(dp)
classSolution: defmaximalRectangle(self, matrix: List[List[str]]) -> int: ifnot matrix ornot matrix[0]: return0 # row, col = len(matrix), len(matrix[0]) # width = [[0]*col for _ in range(row)] # for i in range(row): # for j in range(col): # if j == '0': # width[i][j] = matrix[i][j] # elif matrix[i][j] == '1': # width[i][j] = width[i][j-1] + 1
# res = 0 # for i in range(row): # for j in range(col): # if matrix[i][j] == '0': # continue # wid = width[i][j] # area = wid # for k in range(i-1,-1,-1): # wid = min(wid, width[k][j]) # area = max(area, wid*(i-k+1)) # res = max(res, area) # return res
col = len(matrix[0]) height = [0] * (col + 1) area = 0 for row in matrix: for j inrange(col): height[j] = height[j] + 1if row[j] == '1'else0
stack= [-1] for i inrange(col+1): while height[i] < height[stack[-1]]: h = height[stack.pop()] w = i - stack[-1] -1 area = max(area, w*h) stack.append(i) return area
115. 不同的子序列 (2021.6.21)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defnumDistinct(self, s: str, t: str) -> int: row, col = len(t), len(s) if row > col: return0 dp = [[1]*(col+1)] + [[0]*(col+1) for _ inrange(row)] for i inrange(1, row+1): for j inrange(1, col+1): if t[i-1] == s[j-1]: dp[i][j] = dp[i-1][j-1] + dp[i][j-1] else: dp[i][j] = dp[i][j-1] return dp[-1][-1]
818. 赛车 (2021.6.21)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: dp = {0:0} defracecar(self, target: int) -> int: if target in self.dp: return self.dp[target] n = target.bit_length() if2**n - 1 == target: self.dp[target] = n else: self.dp[target] = self.racecar(2**n -1 - target) + n + 1 for i inrange(n-1): self.dp[target] = min(self.dp[target], self.racecar(target - 2**(n-1) + 2**i) + n + i + 1) return self.dp[target]
字符串
709. 转换成小写字母 (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: deftoLowerCase(self, s: str) -> str: for i in s: if65 <= ord(i) <= 90: s = s.replace(i, chr(ord(i) + 32)) return s
# new = "" # for i in s: # if 65 <= ord(i) <= 90: # i = chr(ord(i) + 32) # new += i # return new
import re classSolution: defmyAtoi(self, s: str) -> int: # if len(s) == 0: return 0 # ls = list(s.strip()) # if len(ls) == 0: # return 0 # sign = -1 if ls[0] == "-" else 1 # if ls[0] in ['+', '-']: # del ls[0] # index, res = 0, 0 # while index < len(ls) and ls[index].isdigit(): # res = res * 10 + ord(ls[index]) - ord('0') # index += 1 # return max(-2**31, min(res*sign, 2**31-1))
ls = re.findall(r'^[-\+]?\d+', s.lstrip()) try: res = int(''.join(ls)) returnmax(-2**31, min(res, 2**31-1)) except: return0
14. 最长公共前缀 (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: deflongestCommonPrefix(self, strs: List[str]) -> str: # res = '' # for index, char in enumerate(strs[0]): # for s in strs[1:]: # if index > len(s)-1 or s[index] != char: # return res # res += char # return res
res = '' for i inzip(*strs): iflen(set(i)) == 1: res += i[0] else: break return res
344. 反转字符串 (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11
classSolution: defreverseString(self, s: List[str]) -> None: """ Do not return anything, modify s in-place instead. """ left, right = 0, len(s)-1 while left < right: s[left], s[right] = s[right], s[left] left += 1 right -= 1 return s
541. 反转字符串 II (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defreverseStr(self, s: str, k: int) -> str: # ls = list(s) # for i in range(0, len(ls), 2*k): # ls[i:i+k] = reversed(ls[i:i+k]) # return ''.join(ls)
ls = list(s) for i inrange(0, len(ls), 2*k): left, right = i, min(i+k-1, len(ls)-1) while left < right: ls[left], ls[right] = ls[right], ls[left] left += 1 right -= 1 return''.join(ls)
# ls = s.split() # left, right = 0, len(ls)-1 # while left < right: # ls[left], ls[right] = ls[right], ls[left] # left += 1 # right -= 1 # return ' '.join(ls)
# left, right = 0, len(s)-1 # while left <= right and s[left] == ' ': # left += 1 # while left <= right and s[right] == ' ': # right -= 1 # d, word = collections.deque(), [] # while left <= right: # if s[left] == ' ' and word: # d.appendleft(''.join(word)) # word = [] # elif s[left] != ' ': # word.append(s[left]) # left += 1 # d.appendleft(''.join(word)) # return " ".join(d)
557. 反转字符串中的单词 III (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11
classSolution: defreverseWords(self, s: str) -> str: # ls = s.split() # res = [] # for word in ls: # res.append(''.join(reversed(word))) # return ' '.join(res)
# return ' '.join(word[::-1] for word in s.split())
classSolution: defreverseOnlyLetters(self, s: str) -> str: d = [char for char in s if char.isalpha()] res = [] for i in s: if i.isalpha(): res.append(d.pop()) else: res.append(i) return''.join(res)
# ls = list(s) # left, right = 0, len(ls)-1 # while left < right: # while left < right and not ls[left].isalpha(): # left += 1 # while left < right and not ls[right].isalpha(): # right -= 1 # ls[left], ls[right] = ls[right], ls[left] # left += 1 # right -= 1 # return ''.join(ls)
from collections import Counter classSolution: deffindAnagrams(self, s: str, p: str) -> List[int]: # lp, res = len(p), [] # pc = Counter(p) # sc = Counter(s[:len(p)-1]) # for i in range(0, len(s)-len(p)+1): # sc[s[i+lp-1]] += 1 # if pc == sc: res.append(i) # sc[s[i]] -= 1 # if sc[s[i]] == 0: # del sc[s[i]] # return res
pc = [0]*26 sc = [0]*26 res = [] iflen(s) < len(p): return res for i inrange(len(p)): pc[ord(p[i])-ord('a')] += 1 sc[ord(s[i])-ord('a')] += 1 if pc == sc: res.append(0) for j inrange(len(p), len(s)): sc[ord(s[j])-ord('a')] += 1 sc[ord(s[j-len(p)])-ord('a')] -= 1 if pc == sc: res.append(j-len(p)+1) return res
125. 验证回文串 (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: defisPalindrome(self, s: str) -> bool: # ls = list(s) # left, right = 0, len(ls)-1 # while left < right: # while left < right and not ls[left].isalnum(): # left += 1 # while left < right and not ls[right].isalnum(): # right -= 1 # if ls[left].lower() != ls[right].lower(): # return False # left += 1 # right -= 1 # return True
ls = ''.join(char.lower() for char in s if char.isalnum()) return ls == ls[::-1]
680. 验证回文字符串 Ⅱ (2021.7.1)
1 2 3 4 5 6 7 8 9 10
classSolution: defvalidPalindrome(self, s: str) -> bool: left, right = 0, len(s)-1 while left < right: if s[left] != s[right]: first, second = s[left:right], s[left+1:right+1] return first == first[::-1] or second == second[::-1] left += 1 right -= 1 returnTrue
最长公共子串 (2021.7.1)
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: deflongestCommonSubstring(self, text1: str, text2: str) -> int: ifnot text1 ornot text2: return0 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] = 0 returnmax(max(row) for row in dp)
# class Solution: # def longestPalindrome(self, s: str) -> str: # res = '' # for i in range(len(s)): # res = max(self.helper(i, i, s), self.helper(i, i+1, s), res, key=len) # return res
# def helper(self, l, r, s): # while l >= 0 and r < len(s) and s[l] == s[r]: # l -= 1 # r += 1 # return s[l+1:r]
classSolution: deflongestPalindrome(self, s: str) -> str: n, max_len, res = len(s), 1, s[0] if n < 2: return s
dp = [[False]*n for _ inrange(n)] for i inrange(n): for j inrange(i): if s[i] == s[j] and (i-j+1 <= 3or dp[i-1][j+1]): dp[i][j] = True if i-j+1 > max_len: max_len = i-j+1 res = s[j:i+1] return res
classSolution: defisMatch(self, s: str, p: str) -> bool: # if not p: return not s # first_match = bool(s) and p[0] in ['.', s[0]] # if len(p) >=2 and p[1] == '*': # return (first_match and self.isMatch(s[1:], p)) or self.isMatch(s, p[2:]) # return first_match and self.isMatch(s[1:], p[1:])
# ls, lp = len(s), len(p) # memo = {} # def dp(i, j): # if (i, j) in memo: return memo[(i, j)] # if j == lp: return i == ls # first_match = (i < ls) and p[j] in [s[i], '.'] # if j <= lp - 2 and p[j+1] == "*": # tmp = dp(i, j+2) or (first_match and dp(i+1, j)) # else: # tmp = first_match and dp(i+1, j+1) # memo[(i, j)] = tmp # return tmp # return dp(0, 0)
m, n = len(p), len(s) dp = [[False]*(n+1) for _ inrange(m+1)] dp[0][0] = True for i inrange(2, m+1): dp[i][0] = dp[i-2][0] and p[i-1] == '*'
for i inrange(1, m+1): for j inrange(1, n+1): if p[i-1] != '*': dp[i][j] = dp[i-1][j-1] and (p[i-1] in [s[j-1], '.']) else: dp[i][j] = dp[i-2][j] if p[i-2] in [s[j-1], '.']: dp[i][j] |= dp[i][j-1] return dp[-1][-1]
44. 通配符匹配 (2021.7.2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defisMatch(self, s: str, p: str) -> bool: m, n = len(s), len(p) dp = [[False]*(n+1) for _ inrange(m+1)] dp[0][0] = True for j inrange(1, n+1): if p[j-1] == '*': dp[0][j] = True else: break
for i inrange(1, m+1): for j inrange(1, n+1): if p[j-1] == '*': dp[i][j] = dp[i][j-1] or dp[i-1][j] else: dp[i][j] = dp[i-1][j-1] and p[j-1] in [s[i-1], '?'] return dp[-1][-1]
classSolution: defisIsomorphic(self, s: str, t: str) -> bool: # n, st, ts = len(s), {}, {} # if n == 0: return False
# for i in range(len(s)): # if s[i] in st and st[s[i]] != t[i]: # return False # if t[i] in ts and ts[t[i]] != s[i]: # return False # st[s[i]] = t[i] # ts[t[i]] = s[i] # return True
# sl, tl = [0]*256, [0]*256 # for i in range(len(s)): # if sl[ord(s[i])] != tl[ord(t[i])]: # return False # sl[ord(s[i])] = i+1 # tl[ord(t[i])] = i+1 # return True