面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
LeetCode 75 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
数组/字符串
1.LC88【合并两个有序数组】
def solve(nums1, m, nums2, n):
p1, p2 = m-1, n-1
tail = m + n -1
while p1 >= 0 or p2 >= 0:
if p1 == -1:
nums1[tail] = nums2[p2]
p2 -= 1
elif p2 == -1:
nums1[tail] = nums1[p1]
p1 -= 1
elif nums1[p1] > nums2[p2]:
nums1[tail] = nums1[p1]
p1 -= 1
else:
nums1[tail] = nums2[p2]
p2 -= 1
tail -= 1
2、LC27【原地移除指定元素】
# 原地删除元素指定值
def solve(nums, val):
n = len(nums)
left = 0
for i in range(n):
if nums[i] != val:
nums[left] = nums[i]
left += 1
return left
3、LC26【原地删除有序数组重复元素】
# 原地删除数组重复元素
def solve(nums):
n = len(nums)
left, right = 1, 1
while right < n:
if nums[right] != nums[right-1]:
nums[left] = nums[right]
left += 1
right += 1
return left
4、LC80【原地删除有序数组重复元素2】
# 原地删除数组重复元素【超过两个的元素只保留两个】
def solve(nums):
n = len(nums)
left, right = 2, 2
while right < n:
if nums[right] != nums[left-2]:
nums[left] = nums[right]
left += 1
right += 1
return left
5、LC1768【交替合并字符串】
# 交替合并字符串
def solve(word1, word2):
m, n = len(word1), len(word2)
p, q = 0, 0
res = []
while p < m or q < n:
if p < m:
res.append(word1[p])
p += 1
if q < n:
res.append(word2[q])
q += 1
return ''.join(res)
6、LC1071【字符串最大公因子】
# 字符串的最大公因子
import math
def solve(str1, str2):
res_len = math.gcd(len(str1), len(str2))
if str1[:res_len] * (len(str1) // res_len) == str1 and str1[:res_len] * (len(str2) // res_len) == str2:
return str1[:res_len]
return ''
7、LC605【种花问题】
# 种花
def solve(flowerbed, n):
i = 0
m = len(flowerbed)
while i < m:
if (flowerbed[i] == 0) and (i==0 or flowerbed[i-1] == 0) and (i==m-1 or flowerbed[i+1] == 0):
i += 2
n -= 1
else:
i += 1
return n <= 0
8、LC345【翻转字符串中的元音字母】
# 翻转元音字母
def solve(s):
n = len(s)
lst = list(s)
i, j = 0, n-1
while i < j:
while i < n and not judge(lst[i]):
i += 1
while j > 0 and not judge(lst[j]):
j -= 1
if i < j:
lst[i], lst[j] = lst[j], lst[i]
i += 1
j -= 1
return ''.join(lst)
def judge(item):
if item in ('a','e','i','o','u','A','E','I','O','U'):
return 1
else:
return 0
9、LC151【翻转字符串中的单词】
# 翻转单词
def solve(s):
s = s.strip()
n = len(s)
i, j = n-1, n-1
res = []
while i >= 0:
while i >= 0 and s[i] != ' ':
i -= 1
res.append(s[i+1:j+1])
while i >= 0 and s[i] == ' ':
i -= 1
j = i
return ' '.join(res)
10、LC238【除自身以外的乘积】
# 除自身以外的数组乘积
def solve(nums):
ans = [1] * len(nums)
# 元素左半部分乘积
for i in range(1, len(nums)):
ans[i] = ans[i-1] * nums[i-1]
# 元素右半部分乘积
ans1 = [1] * len(nums)
for i in range(len(nums)-2,-1,-1):
ans1[i] = ans1[i+1] * nums[i+1]
res = [ans[i] * ans1[i] for i in range(len(ans))]
return res
11、LC334【递增三元子序列】
# 递增的三元子序列
def solve(nums):
n = len(nums)
if n < 3:
return False
small, mid = nums[0], float('inf')
for i in range(n):
if nums[i] > mid:
return True
if nums[i] > small:
mid = nums[i]
else:
small = nums[i]
return False
12、LC443【压缩字符串】
# 压缩字符串
def solve(chars):
def reverse(left, right):
while left < right:
chars[left], chars[right] = chars[right], chars[left]
left += 1
right -= 1
left, write = 0, 0
n = len(chars)
for i in range(n):
if i == n-1 or chars[i] != chars[i+1]:
chars[write] = chars[i]
write += 1
nums = i - left + 1
if nums > 1:
anchor = write
while nums > 0:
chars[write] = str(nums % 10)
write += 1
nums //= 10
reverse(anchor, write-1)
left = i + 1
return write, chars[:write]
13、LC55【跳跃游戏】
# 跳跃游戏
def solve(nums):
n = len(nums)
most = 0
for i in range(n):
if i <= most:
most = max(most, i + nums[i])
if most >= n - 1:
return True
return False
双指针
1、LC283【移动零】
# 移动0
def solve(nums):
i = 0
for j in range(len(nums)):
if nums[j]:
nums[i], nums[j] = nums[j], nums[i]
i += 1
2、LC392【判断子序列】
# 判断子序列
def solve(s, t):
if not s:
return True
i = 0
for c in t:
if s[i] == c:
i += 1
if i == len(s):
return True
return False
3、LC11【盛水最多的容器】
# 盛最多水的容器
def solve(height):
i, j = 0, len(height)-1
res = 0
while i < j:
if height[i] < height[j]:
res = max(res, height[i] * (j-i))
i += 1
else:
res = max(res, height[j] * (j-i))
j -= 1
return res
4、LC167【两数之和 有序数组】
# 两数之和2 有序数组
def solve(nums, target):
left, right = 0, len(nums) - 1
while left < right:
total = nums[left] + nums[right]
if total == target:
return [left + 1, right + 1]
elif total < target:
left += 1
else:
right -= 1
return [-1, -1]
滑动窗口
1、LC643【子数组最大平均数】
# 子数组的最大平均数
def solve(nums,k):
res = total = sum(nums[:k])
for i in range(k,len(nums)):
total = total-nums[i-k]+nums[i]
res = max(res, total)
return res / k
2、LC1456【定长子串中元音的数目】
# 定长字串中元音最大数目
def solve(s, k):
def judge(ch):
return int(ch in 'aeiou')
n = len(s)
start = 0
for i in range(k):
start += judge(s[i])
res = start
for i in range(k,n):
start += judge(s[i]) - judge(s[i-k])
res = max(res, start)
return res
3、LC1004【最大连续1的个数】
# 最大连续1的个数
def solve(nums, k):
n = len(nums)
res = zeros = 0
left = right = 0
while right < n:
if nums[right] == 0:
zeros += 1
while zeros > k:
if nums[left] == 0:
zeros -= 1
left += 1
res = max(res, right-left+1)
right += 1
return res
4、LC1493【删除一个元素后全为1的最长子数组】
# 删除一个元素后全为1的最长子数组
def solve(nums):
ans = 0
p0 = p1 = 0
for i in range(len(nums)):
if nums[i] == 0:
p1, p0 = p0, 0
else:
p0 += 1
p1 += 1
ans = max(ans, p1)
if ans == len(nums):
ans -= 1
return ans
5、LC209【长度最小的子数组】
# 长度最小的子数组
def solve(target, nums):
left, right = 0, 0
ans = len(nums) + 1
total = 0
while right < len(nums):
total += nums[right]
while total >= target:
ans = min(ans, right - left + 1)
total -= nums[left]
left += 1
right += 1
if ans == len(nums) + 1:
return 0
else:
return ans
6、LC3【无重复字符的最长子串】
# 无重复字符的最长子串
def solve(s):
dic = {}
res = 0
i = -1
for j in range(len(s)):
if s[j] in dic:
i = max(dic[s[j]], i)
dic[s[j]] = j
res = max(res, j - i)
return res
前缀和
1、LC1732【找到最高海拔】
# 找到最高海拔
def solve(gain):
ans = total = 0
for each in gain:
total += gain
ans = max(ans, total)
return ans
2、LC724【寻找数组的中心下标】
# 寻找数组的中心下标
def solve(nums):
left, right = 0, sum(nums)
for i in range(len(nums)):
right -= nums[i]
if left == right:
return i
left += nums[i]
return -1
哈希表、哈希集合
1、LC2215【找出两数组的不同】
# 找出两数组的不同
def solve(nums1, nums2):
set1 = set(nums1)
set2 = set(nums2)
res1 = []
res2 = []
for each in set1:
if each not in set2:
res1.append(each)
for each in set2:
if each not in set1:
res2.append(each)
return [res1, res2]
2、LC1207【独一无二的出现次数】
# 独一无二的出现次数
def solve(arr):
dic = {}
for each in arr:
if each in dic:
dic[each] += 1
else:
dic[each] = 1
res = list(dic.values())
return len(res) == len(set(res))
3、LC1657【确定两个字符串是否接近】
# 两个字符串是否接近
def solve(word1, word2):
c1 = [0] * 26
c2 = [0] * 26
for each in word1:
c1[ord(each)-ord('a')] += 1
for each in word2:
c2[ord(each)-ord('a')] += 1
for i in range(26):
if c1[i] + c2[i] == 0:
continue
if c1[i] == 0 or c2[i] == 0:
return False
c1.sort()
c2.sort()
for i in range(26):
if c1[i] != c2[i]:
return False
return True
4、LC2352【相等行列对】
# 相等行列对
def solve(grid):
m, n = len(grid), len(grid[0])
grid_col = [[0] * m for _ in range(n)]
for i, g in enumerate(grid):
for j, x in enumerate(g):
grid_col[j][i] = x
res = 0
for each in grid:
for ee in grid_col:
if each == ee:
res += 1
return res
栈
1、LC2390【从字符串中移除星号】
# 从字符串中移除星号
def solve(s):
stack = []
for each in s:
if each == '*':
stack.pop()
else:
stack.append(each)
return ''.join(stack)
2、LC735【小行星碰撞】
# 小行星碰撞
def solve(asteroids):
stk = []
for t in asteroids:
ok = True
while ok and stk and stk[-1] > 0 and t < 0:
a, b = stk[-1], -t
if a <= b:
stk.pop(-1)
if a >= b:
ok = False
if ok:
stk.append(t)
return stk
3、LC394【字符串解码】
# 字符串解码
def solve(s):
stk = []
res = ''
multi = 0
for each in s:
if each == '[':
stk.append([multi, res])
multi = 0
res = ''
elif each == ']':
cur_multi, cur_res = stk.pop()
res = cur_res + cur_multi * res
elif each >= '0' and each <= '9':
multi = multi * 10 + int(each)
else:
res += each
return res
队列
1、LC649【Dota2 参议院】
# 参议院
def solve(senate):
n = len(senate)
r = collections.deque()
d = collections.deque()
for i, c in enumerate(senate):
if c == 'R':
r.append(i)
if c == 'D':
d.append(i)
while r and d:
if r[0] < d[0]:
r.append(r[0]+n)
else:
d.append(d[0]+n)
r.popleft()
d.popleft()
return 'Radiant' if r else 'Dire'
链表
1、LC2095【删除链表的中间节点】
# 删除链表的中间节点
def solve(head):
if head.next is None:
return None
slow, fast, pre = head, head, None
while fast and fast.next:
pre = slow
slow = slow.next
fast = fast.next.next
pre.next = slow.next
return head
2、LC328【奇偶链表】
# 奇偶链表
def solve(head):
if not head:
return head
evenHead = head.next
odd, even = head, evenHead
while even and even.next:
odd.next = even.next
odd = odd.next
even.next = odd.next
even = even.next
odd.next = evenHead
return head
3、LC206【反转链表】
# 反转链表
def solve(head):
cur, pre = head, None
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
4、LC2130【链表最大孪生和】
# 链表最大孪生和
def solve(head):
# 快慢指针找中点
slow, fast = head, head.next
while fast.next:
slow = slow.next
fast = fast.next.next
# 反转后半部分链表
cur, pre = slow.next, None
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
# 取head和pre的值求和
res = 0
while pre:
cur_res = head.val + pre.val
res = max(cur_res, res)
head = head.next
pre = pre.next
return res
5、字符串转链表
# 字符串转链表
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def solve(s):
prehead = ListNode(-1)
prev = prehead
for each in s:
prev.next = ListNode(each)
prev = prev.next
return prehead.next
二叉树
0、二叉树定义
# 二叉树
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
node1 = TreeNode(2)
node2 = TreeNode(5)
node3 = TreeNode(7)
node4 = TreeNode(9)
node1.left = node2
node1.right = node3
1、LC104【二叉树的最大深度】
深度优先
# 深度优先
def solve(root):
if not root:
return 0
return max(solve(root.left), solve(root.right)) + 1
广度优先
# 广度优先
def solve(root):
if not root:
return 0
quene = [root]
res = 0
while quene:
tmp = []
for node in quene:
if node.left:
tmp.append(node.left)
if node.right:
tmp.append(node.right)
quene = tmp
res += 1
return res
2、LC872【叶子相似的树】
深度优先
# 叶子相似的树
def solve(root1, root2):
def dfs(node):
if not node.left and not node.right:
return [node.val]
elif node.left and not node.right:
return dfs(node.left)
elif not node.left and node.right:
return dfs(node.right)
else:
return dfs(node.left) + dfs(node.right)
return dfs(root1) == dfs(root2)
3、LC1448【统计二叉树中好节点的数目】
#统计二叉树中好节点的数目
def solve(root):
def dfs(root, value):
if not root:
return 0
res = 0
if root.val >= value:
res += 1
value = root.val
res += dfs(root.left, value) + dfs(root.right, value)
return res
return dfs(root, -10**9)
4、LC112【路径总和1】
深度优先
# 深度优先
def solve(root, targetSum):
if not root:
return False
if not root.left and not root.right:
return root.val == targetSum
return solve(root.left, targetSum-root.val) or solve(root.right, targetSum-root.val)
广度优先
def solve(root, tagetSum):
if not root:
return False
quene_node = [root]
quene_val = [root.val]
while quene_node:
tmp_node = quene_node.pop(0)
tmp_val = quene_val.pop(0)
if not tmp_node.left and not tmp_node.right:
if tmp_val == targetSum:
return True
continue
if tmp_node.left:
quene_node.append(tmp_node.left)
quene_val.append(tmp_val + tmp_node.left.val)
if tmp_node.right:
quene_node.append(tmp_node.right)
quene_val.append(tmp_val + tmp_node.right.val)
return False
5、LC113【路径总和2】
回溯
# 路径总和2
# 回溯
def solve(root, targetSum):
res, path = [], []
def back(root, target):
if not root:
return
path.append(root.val)
target -= root.val
if target == 0 and not root.left and not root.right:
res.append(path)
back(root.left, target)
back(root.right, target)
path.pop()
back(root, targetSum)
return res
6、LC437【路径总和3】
深度优先
# 路径总和3
# 深度优先
def solve(root, targetSum):
if not root:
return 0
def kernel(root, targetSum):
if not root:
return 0
res = 0
if root.val == targetSum:
res += 1
res += kernel(root.left, targetSum - root.val)
res += kernel(root.right, targetSum - root.val)
return res
res = kernel(root, targetSum)
res += solve(root.left, targetSum)
res += solve(root.right, targetSum)
return res
7、LC1372【二叉树的最长交错路径】
深度优先
# 二叉树的最长交错路径
def solve(root):
res = 0
def dfs(root, direction, length):
if not root:
return
nonlocal res
res = max(res, length)
if direction == 0:
dfs(root.left, 1, length+1)
dfs(root.right, 0, 1)
if direction == 1:
dfs(root.right, 0, length+1)
dfs(root.left, 1, 1)
dfs(root, 0, 0)
dfs(root, 1, 0)
return res
8、二叉树的最近公共祖先
深度优先
# 二叉树的最近公共祖先
def solve(root, p, q):
if not root or root == p or root == q:
return root
left = solve(root.left, p, q)
right = solve(root.right, p, q)
if not left:
return right
if not right:
return left
return root
二叉树广度优先
1、LC199【二叉树的右视图】
# 二叉树的右视图
def solve(root):
depth = dict()
max_depth = -1
quene = [(root, 0)]
while quene:
node, cur_depth = quene.pop(0)
if node:
max_depth = max(max_depth, cur_depth)
depth[cur_depth] = node.val
quene.append((node.left, cur_depth+1))
quene.append((node.right, cur_depth+1))
res = []
for each in range(max_depth+1):
res.append(depth[each])
return res
2、LC1161【最大层内元素和】
# 最大层内元素和
def solve(root):
ans, num, quene, level = 1, -inf, [root], 1
while quene:
cur = 0
for i in range(len(quene)):
node = quene.pop(0)
cur += node.val
if node.left:
quene.append(node.left)
if node.right:
quene.append(node.right)
if cur > num:
ans = level
num = cur
level += 1
return ans
3、LC700【二叉搜索树中的搜索】
# 二叉搜索树中的搜索
def solve(root, val):
if not root:
return None
while root:
if root.val == val:
return root
root = root.right if root.val < val else root.left
return None
4、LC450【删除二叉搜索树中的节点】
# 删除二叉搜索树中的节点
def solve(root, key):
if not root:
return None
if key > root.val:
root.right = self.solve(root.right, key)
elif key < root.val:
root.left = self.solve(root.left, key)
else:
if not root.right:
return root.left
elif not root.left:
return root.right
elif root.right and root.left:
tmp = root.right
while tmp.left:
tmp = tmp.left
tmp.left = root.left
root = root.right
return root
图-深度优先
1、LC841【钥匙和房间】
深度优先
# 钥匙和房间
# 深度优先
def solve(rooms):
n = len(rooms)
visit = set()
num = 0
def dfs(x):
visit.add(x)
nonlocal num
num += 1
for each in rooms[x]:
if each not in visit:
dfs(each)
dfs(0)
return num == n
广度优先
# 广度优先
def solve(rooms):
n = len(rooms)
num = 0
visit = {0}
quene = [0]
while quene:
x = quene.pop(0)
num += 1
for each in rooms[x]:
if each not in visit:
visit.add(each)
quene.append(each)
return num == n
2、LC547【省份数量】
深度优先
# 省份数量
# 深度优先
def solve(isConnected):
n = len(isConnected)
visit = set()
res = 0
def dfs(i):
for j in range(n):
if isConnected[i][j] == 1 and j not in visit:
visit.add(j)
dfs(j)
for i in range(n):
if i not in visit:
dfs(i)
res += 1
return res
广度优先
# 广度优先
def solve(isConnected):
n = len(isConnected)
res = 0
visit = set()
for i in range(n):
if i not in visit:
quene = [i]
while quene:
j = quene.pop(0)
visit.add(j)
for k in range(n):
if isConnected[j][k] == 1 and k not in visit:
quene.append(k)
res += 1
return res
图-广度优先
1、LC1926【迷宫中离入口最近的出口】
# 迷宫中离入口最近的出口
import collections
def solve(maze, entrance):
m, n = len(maze), len(maze[0])
# print(m,n)
quene = collections.deque([(entrance[0], entrance[1], 0)])
maze[entrance[0]][entrance[1]] = '+'
while quene:
# print(quene)
# break
x, y, d = quene.popleft()
# print(x,y,d)
for nx, ny in [(x+1,y),(x,y+1),(x-1,y),(x,y-1)]:
# print(nx,ny)
if 0 <= nx < m and 0 <= ny < n and maze[nx][ny] == '.':
if nx == 0 or nx == m - 1 or ny == 0 or ny == n - 1:
return d + 1
maze[nx][ny] = '+'
quene.append((nx, ny, d+1))
# print(quene)
# break
return -1
2、LC994【腐烂的橘子】
#腐烂的橘子
def solve(grid):
m, n = len(grid), len(grid[0])
count = 0 # 新鲜橘子的数量
quene = []
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
count += 1
elif grid[i][j] == 2:
quene.append((i, j))
res = 0
while count > 0 and quene:
res += 1
for i in range(len(quene)):
x, y = quene.pop(0)
for nx, ny in [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]:
if 0 <= nx and nx < m and 0 <= ny and ny < n:
if grid[nx][ny] == 1:
grid[nx][ny] = 2
count -= 1
quene.append((nx, ny))
if count > 0:
return -1
return res
堆/优先队列
1、LC215【数组中第k大元素】
快排
# 数组中第k大元素
# 快排
def solve(nums, k):
k = len(nums) - k
start = 0
end = len(nums) - 1
while True:
loc = kernel(nums, start, end)
if loc == k:
return nums[loc]
elif loc < k:
start = loc + 1
else:
end = loc - 1
def kernel(nums, start, end):
low = start
high = end
base = nums[start]
while low < high:
while low < high and nums[high] >= base:
high -= 1
nums[low] = nums[high]
while low < high and nums[low] < base:
low += 1
nums[high] = nums[low]
nums[low] = base
return low
堆排
# 堆排
def solve(nums, k):
n = len(nums)
build_max_heap(nums, n)
for k in range(n-1, n-k-1, -1):
nums[0], nums[k] = nums[k], nums[0]
heapify(nums, k, 0)
return nums[k]
def build_max_heap(nums, n):
i = n // 2
while i >= 0:
heapify(nums, n, i)
i -= 1
def heapify(nums, n, i):
l = 2 * i
r = 2 * i + 1
largest = i
if l < n and nums[l] > nums[i]:
largest = l
if r < n and nums[r] > nums[largest]:
largest = r
if largest != i:
nums[largest], nums[i] = nums[i], nums[largest]
heapify(nums, n, largest)
二分查找
链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
1、LC374【猜数字大小】
# 猜数字大小
def solve(n):
left, right = 1, n
while left < right:
mid = left + (right - left) // 2
if guess(mid) <= 0:
right = mid
else:
left = mid + 1
return left
2、LC2300【咒语和药水的成功对数】
# 咒语和药水的成功对数
def solve(spells, potions, success):
res = [0] * len(spells)
idx = [i for i in range(len(spells))]
idx.sort(key=lambda x:spells[x])
potions.sort(key=lambda x:-x)
j = 0
for p in idx:
v = spells[p]
while j < len(potions) and potions[j] * v >= success:
j += 1
res[p] = j
return res
3、LC162【寻找峰值】
# 寻找峰值
def solve(nums):
n = len(nums)
left, right = 0, n-1
while left < right:
mid = left + (right - left) // 2
if nums[mid] > nums[mid+1]:
right = mid
else:
left = mid + 1
return right
4、LC875【爱吃香蕉的珂珂】
# 爱吃香蕉的珂珂
import math
def solve(piles, h):
l, r = 1, max(piles)
while l < r:
mid = l + (r - l) // 2
# mid = (l + r) // 2
print(mid)
if check(mid, piles, h):
r = mid
else:
l = mid + 1
return r
def check(mid, piles, h):
cost = 0
for each in piles:
cur = math.ceil(each / mid)
cost += cur
return cost <= h
回溯
1、LC17【电话号码的字母组合】
# 字母组合
def solve(digits):
if not digits:
return []
mapping = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
res = []
path = []
n = len(digits)
if n == 0:
return n
def back(i):
if i == n:
res.append(''.join(path))
return
for each in mapping[int(digits[i])]:
path.append(each)
back(i+1)
path.pop()
back(0)
return res
2、LC46【全排列】
# 全排列
def solve(nums):
n = len(nums)
res = []
def back(i):
if i == n - 1:
res.append(nums[:])
return
for j in range(i, n):
nums[i], nums[j] = nums[j], nums[i]
back(i + 1)
nums[i], nums[j] = nums[j], nums[i]
back(0)
return res
3、LC39【组合总和】【同一个数字可以多次使用】
# 组合总和
def solve(candidates, target):
res = []
path = []
candidates.sort()
start = 0
n = len(candidates)
def back(path, target, candidates, start, res):
if target == 0:
res.append(path[:])
return
for i in range(start, n):
if target - candidates[i] < 0:
break
path.append(candidates[i])
back(path, target-candidates[i], candidates, i, res)
path.pop()
back(path, target, candidates, start, res)
return res
4、LC40【组合总和2】【同一个数字只能用一次】
# 组合总和2
def solve(candidates, target):
res = []
path = []
candidates.sort()
start = 0
n = len(candidates)
def back(path, target, candidates, start, res):
if target == 0:
res.append(path[:])
return
for i in range(start, n):
if target - candidates[i] < 0:
break
# 与组合1不同之处
if i > start and candidates[i] == candidates[i-1]:
continue
path.append(candidates[i])
# 与组合1不同之处
back(path, target-candidates[i], candidates, i+1, res)
path.pop()
back(path, target, candidates, start, res)
return res
动态规划一维
1、LC1137【泰波那契数】
# 泰波那契数
def solve(n):
if n < 2:
return n
f = [0, 0, 1]
# if n < 3:
# return f[n]
s = 1
f0, f1, f2 = f[0], f[1], f[2]
for i in range(3, n+1):
f0 = f1
f1 = f2
f2 = s
s = f0 + f1 + f2
return s
2、LC746【最小花费爬楼梯】
# 最小花费爬楼梯
def solve(cost):
n = len(cost)
dp = [0] * (n+1)
for i in range(2, n+1):
dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
return dp[n]
3、LC198【打家劫舍】
# 打家劫舍
def solve(nums):
n = len(nums)
dp = [0] * n
if n == 1:
return nums[0]
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, n):
dp[i] = max(dp[i-1], dp[i-2]+nums[i])
return dp[n-1]
4、LC322【零钱兑换】
# 零钱兑换
def solve(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for i in range(coin, amount + 1):
dp[i] = min(dp[i], dp[i - coin] + 1)
if dp[amount] != float('inf'):
return dp[amount]
else:
return -1
5、LC518【零钱兑换2】
# 零钱兑换
def solve(amount, coins):
dp = [0] * (amount + 1)
dp[0] = 1
for coin in coins:
for i in range(coin,amount+1):
dp[i] += dp[i-coin]
return dp[amount]
动态规划二维
1、LC62【不同路径】
# 不同路径
def solve(m, n):
dp = [[0] * n for i in range(m)]
for i in range(n):
dp[0][i] = 1
for j in range(m):
dp[j][0] = 1
for i in range(1,m):
for j in range(1,n):
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m-1][n-1]
2、LC1143【最长公共子序列】
# 最长公共子序列
def solve(text1, text2):
m, n = len(text1), len(text2)
dp = [[0] * (n+1) for i in range(m+1)]
res = 0
for i in range(1, m+1):
for j in range(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])
res = max(res, dp[i][j])
return res
3、LC714【买卖股票的最佳时机】【含手续费】
# 买卖股票的最佳时机【含手续费】
def solve(prices, fee):
n = len(prices)
dp = [[0] * 2 for i in range(n)]
dp[0][1] = -prices[0]
for i in range(1, n):
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i] - fee)
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
return dp[n-1][0]
4、LC72【编辑距离】
# 编辑距离
def solve(word1, word2):
m, n = len(word1), len(word2)
dp = [[0] * (n+1) for i in range(m+1)]
for i in range(1, m+1):
dp[i][0] = dp[i-1][0] + 1
for j in range(1, n+1):
dp[0][j] = dp[0][j-1] + 1
for i in range(1, m+1):
for j in range(1, n+1):
if word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1]
else:
dp[i][j] = min(dp[i-1][j-1]+1, dp[i-1][j]+1, dp[i][j-1]+1)
return dp[m][n]
位运算
1、LC338【比特位计数】
# 比特位计数
def solve(n):
res = []
def count(x):
cnt = 0
while x > 0:
x = x & (x - 1)
cnt += 1
return cnt
for i in range(n+1):
res.append(count(i))
return res
2、LC136【只出现一次的数字】
# 只出现一次的数字
def solve(nums):
x = 0
for each in nums:
x = x ^ each
return x
区间集合
1、LC435【无重叠区间】
# 无重叠区间
def solve(intervals):
n = len(intervals)
intervals.sort(key=lambda x:x[1])
right = intervals[0][1]
ans = 1
for i in range(1, n):
if intervals[i][0] >= right:
ans += 1
right = intervals[i][1]
return n - ans
2、LC452【用最少数量的箭引爆气球】
# 用最少数量的箭引爆气球
def solve(points):
n = len(points)
points.sort(key=lambda x:x[1])
right = points[0][1]
ans = 1
for i in range(1, n):
if points[i][0] > right:
ans += 1
right = points[i][1]
return ans
单调栈
1、LC739【每日温度】
# 每日温度
def solve(temperatures):
n = len(temperatures)
stack = []
ans = [0] * n
for i in range(n):
cur = temperatures[i]
while stack and cur > temperatures[stack[-1]]:
pre_index = stack.pop()
ans[pre_index] = i - pre_index
stack.append(i)
return ans
2、LC901【股票价格的跨度】
class StockSpanner:
def __init__(self):
self.stack = [(-1, inf)]
self.idx = -1
def next(self, price: int) -> int:
self.idx += 1
while price >= self.stack[-1][1]:
self.stack.pop()
self.stack.append((self.idx, price))
return self.idx - self.stack[-2][0]
# Your StockSpanner object will be instantiated and called as such:
# obj = StockSpanner()
# param_1 = obj.next(price)