LeetCode热题100
- 22. 括号生成(🎂)
- 76. 最小覆盖子串(🎂)
- 15. 三数之和(🎂)
- 105. 从前序与中序遍历序列构造二叉树(🎂)
- 56. 合并区间(🎂)
- 200. 岛屿数量
- 105. 岛屿的最大面积
- 463. 岛屿的周长(🎂)
- 827. 最大人工岛(🎂)
- 239. 滑动窗口最大值
- 17. 电话号码的字母组合
- 75. 颜色分类
- 79. 单词搜索
- 32. 最长有效括号(🎂)
- 33. 搜索旋转排序数组(🎂)
- 39. 组合总和
- 48. 旋转图像(🎂)
- 64. 最小路径和
- 70. 爬楼梯
- 72. 编辑距离(🎂 原问题很简单,注意变体,添加了转换成本)
- 78. 子集
- 49. 字母异位词分组
- 98. 验证二叉搜索树(🎂)
- 114. 二叉树展开为链表
- 121. 买卖股票的最佳时机
- 128. 最长连续序列(🎂)
- 136. 只出现一次的数字
- 139. 单词拆分
- 141. 环形链表
- 142. 环形链表 II
- 152. 乘积最大子数组(🎂)
- 160. 相交链表
- 169. 多数元素
- 198. 打家劫舍(🎂)
- 221. 最大正方形(🎂注意最大矩形)
- 剑指 Offer II 040. 矩阵中最大的矩形(🎂)
- 234. 回文链表(🎂)
- 238. 除自身以外数组的乘积(🎂)
- 236. 二叉树的最近公共祖先(🎂)
- 240. 搜索二维矩阵 II
- 279. 完全平方数(🎂)
- 283. 移动零
- 287. 寻找重复数
- 300. 最长递增子序列(🎂🎂)
- 309. 最佳买卖股票时机含冷冻期(🎂🎂)
- 322. 零钱兑换(🎂)
- 347. 前 K 个高频元素
- 617. 合并二叉树(🎂)
- 461. 汉明距离
- 448. 找到所有数组中消失的数字
- 560. 和为 K 的子数组(🎂)
- 739. 每日温度(🎂)
- 309. 最佳买卖股票时机含冷冻期(🎂)
- 647. 回文子串(🎂)
- 438. 找到字符串中所有字母异位词
- 406. 根据身高重建队列(🎂)
- 338. 比特位计数(🎂)
- 543. 二叉树的直径(🎂)
- 337. 打家劫舍 III(🎂)
- 84. 柱状图中最大的矩形(🎂)
- 538. 把二叉搜索树转换为累加树
- 208. 实现 Trie (前缀树)
- 394. 字符串解码(🎂)
- 416. 分割等和子集(🎂)
- 494. 目标和(🎂)
- 148. 排序链表(🎂归并排序)
- 96. 不同的二叉搜索树(🎂)
- 450. 删除二叉搜索树中的节点(🎂)
- 581. 最短无序连续子数组(🎂 挺巧妙的)
22. 括号生成(🎂)
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
res = []
def backtracking(S, left, right):
if len(S) == 2*n:
res.append(''.join(S))
return
if left < n:
S.append('(')
backtracking(S, left+1, right)
S.pop()
# 这里是右括号的数目要小于左括号的数目
if right < left:
S.append(')')
backtracking(S, left, right+1)
S.pop()
backtracking([], 0, 0)
return res
76. 最小覆盖子串(🎂)
class Solution:
def minWindow(self, s: str, t: str) -> str:
m, n = len(s), len(t)
if m < n: return ''
dic_t = collections.Counter(t)
def is_in(dic, dic_t):
for k, v in dic_t.items():
if dic[k] <= 0: return False
if dic[k] < dic_t[k]: return False
return True
dic = collections.defaultdict(int)
l, r = 0, 0
min_length = float('inf')
res = ''
while r < m:
while r < m and not is_in(dic, dic_t):
dic[s[r]] += 1
r += 1
while l < r and is_in(dic, dic_t):
if r-l < min_length:
min_length = r - l
res = s[l:r]
dic[s[l]] -=1
l += 1
return res
15. 三数之和(🎂)
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 使用双指针的解法,可以使得复杂度降低到O(n^2)
res, k = [], 0
nums.sort()
for k in range(len(nums) - 2):
if nums[k] > 0: break
if k > 0 and nums[k] == nums[k-1]: continue
l, r = k+1, len(nums) - 1
while l < r:
s = nums[k] + nums[l] + nums[r]
if s < 0:
# 太小了,右移左指针
l += 1
while l < r and nums[l] == nums[l-1]: l += 1
elif s > 0:
# 太大了,减小右指针
r -= 1
while l < r and nums[r] == nums[r+1]: r -= 1
else:
# 刚刚好
res.append([nums[k], nums[l], nums[r]])
# 可以趁机继续剪枝
l += 1
r -= 1
while l < r and nums[l] == nums[l-1]: l += 1
while l < r and nums[r] == nums[r+1]: r -= 1
return res
105. 从前序与中序遍历序列构造二叉树(🎂)
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
# 先序遍历的第一个元素肯定是根节点, [根节点, 左子树, 右子树]
# 中序遍历的结果是,[左子树,根节点,右子树]
# 因此,第一步先通过先序遍历的第一个元素找到根节点,再在中序遍历中找到根节点所对应的位置,
if not preorder: return None
root_val = preorder[0]
root = TreeNode(root_val)
seperate_idx = inorder.index(root_val)
left_inorder = inorder[:seperate_idx]
right_inorder = inorder[seperate_idx+1:]
left_preorder = preorder[1:1+len(left_inorder)]
right_preorder = preorder[1+len(left_inorder):]
root.left = self.buildTree(left_preorder, left_inorder)
root.right = self.buildTree(right_preorder, right_inorder)
return root
此外,从三种遍历中任意取两个出来,都可以恢复这个二叉树。
56. 合并区间(🎂)
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
n = len(intervals)
if n < 2: return intervals
intervals = sorted(intervals, key=lambda x: x[0]) # 按照左边界进行排序
res = []
l, r = 0, 1
while r < n:
left = intervals[l][0]
right = intervals[l][1]
while r < n and intervals[r][0] <= right:
right = max(intervals[r][1], right)
r += 1
res.append([left, right])
l = r
r += 1
if l == n - 1:
res.append(intervals[l])
return res
200. 岛屿数量
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
def dfs(i, j):
# 终止条件
if not (0 <= i < len(grid)) or not (0 <= j < len(grid[0])): return
if grid[i][j] == '0': return
# 内部逻辑
grid[i][j] = '0' # 淹没该陆地
up = dfs(i-1, j)
down = dfs(i+1, j)
left = dfs(i, j-1)
right = dfs(i, j+1)
return
m, n = len(grid), len(grid[0])
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == '1':
dfs(i, j)
res += 1
return res
105. 岛屿的最大面积
class Solution:
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
def dfs(i, j):
if not (0 <= i < len(grid)) or not (0 <= j < len(grid[0])): return 0
if grid[i][j] == 0: return 0
# 内部逻辑
grid[i][j] = 0 # 淹没陆地
return 1 + dfs(i-1, j) + dfs(i+1, j) + dfs(i, j-1) + dfs(i, j+1)
m, n = len(grid), len(grid[0])
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
area = dfs(i, j)
res = max(res, area)
return res
463. 岛屿的周长(🎂)
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
res = 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
res += 4
# 如果上下左右有相邻的陆地,有一块就要减去1
for dx, dy in [[-1, 0], [1, 0], [0, -1], [0, 1]]:
x, y = i + dx, j + dy
if 0 <= x < m and 0 <= y < n and grid[x][y] == 1:
res -= 1
return res
如果有多块陆地,下面的递归方法稍微改一下,价格计数器,每次dfs完把当前岛的周长加到计数器上,最后一起返回就行了。
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
def dfs(i, j):
if not (0 <= i < len(grid)) or not (0 <= j < len(grid[0])): return 1 # 边界
if grid[i][j] == 0: return 1 # 水
if grid[i][j] != 1: return 0 # 走过了
grid[i][j] = 2 # 走过的路标记一下
return dfs(i-1, j) + dfs(i+1, j) + dfs(i, j-1) + dfs(i, j+1)
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
return dfs(i, j)
827. 最大人工岛(🎂)
239. 滑动窗口最大值
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
q = [(-nums[i], i) for i in range(k)]
heapq.heapify(q)
res = [-q[0][0]]
n = len(nums)
for i in range(k, n):
heapq.heappush(q, (-nums[i], i))
while q[0][1] <= i - k:
heapq.heappop(q)
res.append(-q[0][0])
return res
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
q = []
for i in range(k):
while q and nums[i] >= nums[q[-1]]:
q.pop()
q.append(i)
res = [nums[q[0]]]
for i in range(k, len(nums)):
while q and nums[i] >= nums[q[-1]]:
q.pop()
q.append(i)
while q and q[0] <= i - k:
q.pop(0)
res.append(nums[q[0]])
return res
17. 电话号码的字母组合
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if not digits: return []
dic = {
'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno',
'7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
paths, path = [], []
def backtracking(i, path):
if len(path) >= len(digits):
paths.append(''.join(path))
return
for digit in dic[digits[i]]:
path.append(digit)
backtracking(i+1, path)
path.pop()
backtracking(0, path)
return paths
75. 颜色分类
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def quickSort(i, j):
if i