if n <= 2: return n return self.climbStairs(n-2) + self.climbStairs(n-1)
2. 迭代法
1 2 3 4 5 6
classSolution: defclimbStairs(self, n: int) -> int: a = b = 1 for i inrange(n): a, b = b, a + b return a
22. 括号生成 (2021.3.16)
1. 动态规划(打死我也想不出来的方法~)
1 2 3 4 5 6 7 8
classSolution: defgenerateParenthesis(self, n: int) -> List[str]: res = [[] for _ inrange(n+1)] res[0] = [""] for i inrange(n+1): for j inrange(i): res[i] += ["(" + x + ")" + y for x in res[j] for y in res[i-j-1]] return res[n]
2. 递归 + 剪枝
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defgenerateParenthesis(self, n: int) -> List[str]: res = [] defrecursion(left, right, res, n, str_): if (left == n) and (right == n): res.append(str_) returnNone if left < n: recursion(left+1, right, res, n, str_ + '(') if left > right: recursion(left, right+1, res, n, str_ + ')')
classSolution: defsolveNQueens(self, n: int) -> List[List[str]]: if n < 1: return [] self.res = [] self.col = set() self.pie = set() self.na = set() self.dfs(0, n, []) return [[col*"." + "Q" + (n-col-1)*"."for col in sub_res] for sub_res in self.res]
defdfs(self, row, n, cur): # 递归终止条件 if row >= n: self.res.append(cur) returnNone
for col inrange(n): # 条件判断 if (col in self.col) or (row + col in self.pie) or (row - col in self.na): continue self.col.add(col) self.pie.add(row + col) self.na.add(row - col) # 下探到下一层递归 self.dfs(row+1, n, cur+[col]) # 恢复当前层状态空间 self.col.remove(col) self.pie.remove(row + col) self.na.remove(row - col)
classSolution: defsolveNQueens(self, n: int) -> List[List[str]]: if n < 1: return [] self.res = [] self.dfs(n, 0, 0, 0, 0, []) return [['.'*sub_res + 'Q' + '.'*(n-sub_res-1) for sub_res in res] for res in self.res]
defdfs(self, n, row, col, pie, na, cur): if row >= n: self.res.append(cur) return
return1 == max(list(collections.Counter( x for i, row inenumerate(board) for j, c inenumerate(row) if c != '.' for x in ((c, i), (j, c), ((i//3)*3 + j//3, c, "#")) ).values()) + [1])
defchange(str1, str2): count = 0 for i, char inenumerate(str1): if char != str2[i]: count += 1 if count == 1: returnTrue else: returnFalse
res = [[beginWord]] res_len = []
while res: cada = res.pop(0) for word in wordList: if word notin cada: if change(word, cada[-1]): cada.append(word) if word == endWord: res_len.append(len(cada)) res.append(cada[:]) cada.pop() iflen(res_len) == 0: return0 else: returnmin(res_len)
wordList = list(set(wordList)) if beginWord in wordList: wordList.remove(beginWord) if endWord notin wordList: return0
res = [[beginWord, 1]]
while res: cada = res.pop(0) for i inrange(len(cada[0])): for j in string.ascii_lowercase: next_word = cada[0][:i] + j + cada[0][i+1:] if next_word in wordList: wordList.remove(next_word) if next_word == endWord: return cada[1]+1 res.append([next_word, cada[1]+1]) return0
wordList = set(wordList) if beginWord in wordList: wordList.remove(beginWord) if endWord notin wordList: return0
res = collections.deque([[beginWord, 1]])
while res: word, length = res.popleft() if word == endWord: return length for i inrange(len(word)): for j in string.ascii_lowercase: next_word = word[:i] + j + word[i+1:] if next_word in wordList: wordList.remove(next_word) res.append([next_word, length+1]) return0
wordList = set(wordList) front = {beginWord} back = {endWord} dist = 1 word_len = len(beginWord)
while front: dist += 1 next_set = set() for word in front: for i inrange(word_len): for c in string.ascii_lowercase: if c != word[i]: new_word = word[:i] + c + word[i+1:] if new_word in back: return dist if new_word in wordList: next_set.add(new_word) wordList.remove(new_word) front = next_set iflen(front) > len(back): front, back = back, front return0
m = len(text1) n = len(text2) length = [[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]: length[i][j] = length[i-1][j-1] + 1 else: length[i][j] = max(length[i-1][j], length[i][j-1])
defmergeSort(arr, left, right): if right <= left: return0 mid = (left + right) >> 1 count = mergeSort(arr, left, mid) + mergeSort(arr, mid+1, right) temp = [0] * (right - left + 1) i, t, k = left, left, 0 for j inrange(mid+1, right+1): while (i<=mid) and (arr[i]<=2*arr[j]): i += 1 while (t<=mid) and (arr[t]<arr[j]): temp[k] = arr[t] k += 1; t += 1 temp[k] = arr[j]; k += 1 count += mid - i + 1 while t<=mid: temp[k] = arr[t] k += 1; t += 1 for p inrange(k): arr[left+p] = temp[p] return count
defextend(s, left, right): while left >= 0and right < self.length and s[left] == s[right]: if right-left+1 > self.max_len: self.max_len = right-left+1 self.start = left left -= 1 right += 1
for i inrange(self.length): extend(s, i, i) extend(s, i, i+1) return s[self.start:self.start+self.max_len]
10. 正则表达式匹配 (2021.4.19)
1. DP (暴力)
1 2 3 4 5 6 7 8
classSolution: defisMatch(self, s: str, p: str) -> bool: ifnot p: returnnot s first_match = bool(s) and p[0] in [s[0], '.'] iflen(p) >= 2and p[1] == '*': return self.isMatch(s, p[2:]) or (first_match and self.isMatch(s[1:], p)) else: return first_match and self.isMatch(s[1:], p[1:])
2. DP (带缓存)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defisMatch(self, s: str, p: str) -> bool: s_length, p_length = len(s), len(p) memo = {} defdp(i, j): if (i, j) in memo: return memo[(i, j)] if j == p_length: return i == s_length first_match = i < s_length and p[j] in [s[i], '.'] if j <= p_length-2and 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)
115. 不同的子序列 (2021.4.19)
1 2 3 4 5 6 7 8 9 10 11
classSolution: defnumDistinct(self, s: str, t: str) -> int: s_length, t_length = len(s), len(t) dp = [[1]*(s_length+1)] + [[0]*(s_length+1) for _ inrange(t_length)] for i inrange(1, t_length + 1): for j inrange(1, s_length + 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[t_length][s_length]
283. 移动零 (2021.5.12)
使用 j 指针记录非零元素应该填入的位置
1 2 3 4 5 6 7 8 9 10
classSolution: defmoveZeroes(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ j = 0 for i inrange(len(nums)): if nums[i] != 0: nums[i], nums[j] = nums[j], nums[i] j += 1
11. 盛最多水的容器
双指针夹逼法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defmaxArea(self, height: List[int]) -> int: # max_area = 0 # for i in range(len(height)): # for j in range(i, len(height)): # area = (j-i) * min(height[i], height[j]) # max_area = max(max_area, area) # return max_area
max_area = 0 left, right = 0, len(height)-1 while(left < right): area = (right - left) * min(height[left], height[right]) max_area = max(max_area, area) if height[left] < height[right]: left += 1 else: right -= 1 return max_area
70. 爬楼梯 (2021.5.13)
找最近重复子问题
1 2 3 4 5 6 7 8
classSolution: defclimbStairs(self, n: int) -> int: if n <= 2: return n f1, f2 = 1, 2 for i inrange(3, n + 1): f1, f2 = f2, f1+f2 return f2
1. 两数之和
1. 暴力法 —-> 两重循环 2. 哈希表
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: deftwoSum(self, nums: List[int], target: int) -> List[int]: # for i in range(len(nums)): # for j in range(i+1, len(nums)): # if nums[i] + nums[j] == target: # return [i, j]
hash_dic = dict() for i, num inenumerate(nums): if target - num in hash_dic: return [i, hash_dic[target - num]] hash_dic[num] = i return []
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: # result = [] # for index, target in enumerate(nums): # for i in range(index+1, len(nums)): # for j in range(i+1, len(nums)): # if nums[i] + nums[j] + target == 0: # result.append([nums[i], nums[j], target]) # return result
# result = set() # nums.sort() # for index, target in enumerate(nums): # left = index + 1 # right = len(nums) - 1 # while(left < right): # if target + nums[left] + nums[right] == 0: # result.add((target, nums[left], nums[right])) # left += 1 # right -= 1 # elif nums[left] + nums[right] > -target: # right -= 1 # else: # left += 1 # return list(result)
result = [] nums.sort() for index, target inenumerate(nums): left = index + 1 right = len(nums) - 1 if index > 0and nums[index] == nums[index - 1]: continue while(left < right): sum = target + nums[left] + nums[right] ifsum > 0: right -= 1 elifsum < 0: left += 1 else: result.append([target, nums[left], nums[right]]) while (left < right and nums[left] == nums[left + 1]): left += 1 while (left < right and nums[right] == nums[right - 1]): right -= 1 left += 1 right -= 1 return result
# visited = set() # while head: # if head in visited: # return head # else: # visited.add(head) # head = head.next # return None
fast, slow = head, head whileTrue: ifnot (fast and fast.next): returnNone fast, slow = fast.next.next, slow.next if fast == slow: break fast = head while fast != slow: fast, slow = fast.next, slow.next return fast
292. Nim 游戏 (2021.9.18)
数学推理
1 2 3 4 5 6
classSolution: defcanWinNim(self, n: int) -> bool: if n % 4 == 0: returnFalse else: returnTrue
36. 有效的数独 (2021.9.18)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: defisValidSudoku(self, board: List[List[str]]) -> bool: row = [{} for _ inrange(9)] col = [{} for _ inrange(9)] block = [{} for _ inrange(9)]
for i inrange(len(board)): for j inrange(len(board[0])): num = board[i][j] if num != '.': 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: defpeakIndexInMountainArray(self, arr: List[int]) -> int: # for i, num in enumerate(arr): # if num > arr[i+1]: # return i
left, right, res = 0, len(arr)-1, -1 while left <= right: mid = (left + right) // 2 if arr[mid] > arr[mid+1]: right = mid - 1 res = mid else: left = mid + 1 return res
classSolution: deffizzBuzz(self, n: int) -> List[str]: # res = [] # for i in range(n): # index = i + 1 # if index % 15 == 0: # res.append('FizzBuzz') # elif index % 5 == 0: # res.append('Buzz') # elif index % 3 == 0: # res.append('Fizz') # else: # res.append(str(index)) # return res
ans = [] for i inrange(1, n + 1): s = '' if i % 3 == 0: s += 'Fizz' if i % 5 == 0: s += 'Buzz' if s == '': s = str(i) ans.append(s) return ans