[Leetcode]Top 150
数组,字符串
最后一个单词长度
class Solution:
def lengthOfLastWord(self, s: str) -> int:
end = len(s) - 1
while s[end] == " ":
end -= 1
start = end
while start >= 0 and ("a" <= s[start] <= "z" or "A" <= s[start] <= "Z"):
start -= 1
return end - start
买卖股票的最佳时机
class Solution:
def maxProfit(self, prices: List[int]) -> int:
length = len(prices)
low = prices[0]
count = 0
for i in range(1,length):
if prices[i] > low:
count = max(count,prices[i] - low)
else:
low = min(low,prices[i])
return count
买卖股票的最佳时机II
class Solution:
def maxProfit(self, prices: List[int]) -> int:
length = len(prices)
count = 0
for i in range(1,length):
if prices[i] > prices[i-1]:
count += (prices[i] - prices[i-1])
return count
轮转数组
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def reverse(nums,start,end):
left = start
right = end
while left < right:
nums[left],nums[right] = nums[right],nums[left]
left += 1
right -= 1
k = k % len(nums)
reverse(nums,0,len(nums)-1)
reverse(nums,0,k-1)
reverse(nums,k,len(nums)-1)
移除有序数组中的重复项
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
first = 0
last = 1
while last <= len(nums)-1:
if nums[last] != nums[first]:
nums[first+1] = nums[last]
first += 1
last += 1
return first + 1
移除有序数组中的重复项II
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
first = 1
last = 2
while last <= len(nums)-1:
if nums[last] != nums[first -1]:
nums[first+1] = nums[last]
first += 1
last += 1
return first + 1
多数元素
class Solution:
def majorityElement(self, nums: List[int]) -> int:
count = 1
c = nums[0]
for i in range(1,len(nums)):
if count == 0:
count = 1
c = nums[i]
elif nums[i] == c:
count += 1
else:
count -= 1
return c
合并两个有序数组
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
p = m - 1
q = n - 1
index = len(nums1) - 1
while p >= 0 and q >= 0:
if nums1[p] >= nums2[q]:
nums1[index] = nums1[p]
p -= 1
else:
nums1[index] = nums2[q]
q-= 1
index -= 1
while q>=0:
nums1[index] = nums2[q]
index -= 1
q -= 1
移除元素
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
first = -1
last = 0
while last <= len(nums)-1:
if nums[last] != val:
nums[first+1] = nums[last]
first += 1
last += 1
return first + 1
最长公共前缀
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
n = len(strs)
length = len(strs[0])
for s in strs:
length = min(length,len(s))
res = ""
for i in range(length):
start = strs[0][i]
for j in range(n):
if strs[j][i] != start:
return res
res += start
return res
整数转罗马数字
class Solution:
def intToRoman(self, num: int) -> str:
digit_to_str = {
"1000":"M","900":"CM",
"500":"D","400":"CD",
"100":"C","90":"XC",
"50":"L","40":"XL",
"10":"X","9":"IX",
"5":"V","4":"IV",
"1":"I",
}
res = ""
while num>=1:
for key,value in digit_to_str.items():
while num >= int(key):
num-=int(key)
res+=value
return res
罗马数字转整数
class Solution:
def romanToInt(self, s: str) -> int:
dict = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
n = len(s)
index = 0
counter = 0
while index <= n-1:
if index +1 <= n-1 and dict[s[index+1]]>dict[s[index]]:
counter += (dict[s[index+1]]- dict[s[index]])
index += 2
else:
counter += dict[s[index]]
index += 1
return counter
反转字符串中的单词
class Solution:
def reverseWords(self, s: str) -> str:
start = 0
end = len(s) - 1
while start <= len(s) - 1:
if s[start] == ' ':
start += 1
else:
break
while end >= 0:
if s[end] == ' ':
end -=1
else:
break
words = s[start:end+1].split()
return ' '.join(words[::-1])
z字形变换
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1:
return s
res = [""] * numRows
cur = 0
next = 0
for c in s:
cur += next
res[cur] += c
if cur == 0:
next = 1
elif cur == numRows - 1:
next = -1
return ("".join(res))
找出字符串中第一个匹配的下标
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
length_a = len(haystack)
length_b = len(needle)
if length_b > length_a:
return -1
index_a = 0
index_b = 0
while index_a <= length_a - 1:
while index_a <= length_a - 1 and haystack[index_a] != needle[index_b]:
index_a += 1
if index_a <= length_a - length_b:
res = index_a
for _ in range(length_b):
if haystack[index_a] == needle[index_b]:
index_a += 1
index_b += 1
else:
index_a = res + 1
index_b = 0
break
if index_b == length_b:
return res
else:
return -1
return -1
H指数
class Solution:
def hIndex(self, citations: List[int]) -> int:
length = len(citations)
citations.sort()
h = 0
for i in range(length - 1, -1, -1):
h = max(h, min(citations[i], length - i))
return h
O(1)时间插入,删除,获取随机元素
class RandomizedSet:
def __init__(self):
self.map = {}
def insert(self, val: int) -> bool:
if val not in self.map:
self.map[val] = 1
return True
else:
return False
def remove(self, val: int) -> bool:
if val in self.map:
del self.map[val]
return True
else:
return False
def getRandom(self) -> int:
return random.choice(list(self.map.keys()))
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
加油站
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
gass = sum(gas)
costs = sum(cost)
if gass < costs:
return -1
else:
n = len(gas)
start = 0
stock = 0
for i in range(n):
if gas[i] + stock >= cost[i]:
stock = gas[i] + stock - cost[i]
else:
start = i + 1
stock = 0
return start
除自身以外数组的乘积
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
left = nums[:]
right = nums[:]
for i in range(1,n):
left[i] = nums[i] * left[i-1]
for i in range(n-2,-1,-1):
right[i] = nums[i] * right[i+1]
dp = [0]*n
dp[0] = right[1]
dp[-1] = left[n-2]
for i in range(1,n-1):
dp[i] = left[i-1] * right[i+1]
return dp
跳跃游戏
class Solution:
def canJump(self, nums: List[int]) -> bool:
if not nums or len(nums) == 1:
return True
cur = 0
maxindex = nums[0]
while cur <= maxindex:
maxindex = max(maxindex,nums[cur]+cur)
if maxindex >= len(nums) - 1:
return True
cur += 1
return False
跳跃游戏II
class Solution:
def jump(self, nums: List[int]) -> int:
if not nums or len(nums) == 1:
return 0
cur = 0
maxindex = nums[0]
count = 0
while cur <= maxindex:
if cur + nums[cur] >= len(nums) - 1:
return count + 1
nextstep = cur+1
for i in range(1,nums[cur]+1):
if cur + i <= len(nums)-1 and nums[cur + i] + cur + i > maxindex:
maxindex = nums[cur + i] + cur + i
nextstep = cur + i
cur = nextstep
count += 1
双指针
验证回文串
class Solution:
def isPalindrome(self, s: str) -> bool:
t = []
for c in s:
if 'A'<=c<='Z' or 'a'<= c<='z' or '0'<=c<='9':
t.append(c.lower())
if len(t) == 0 or len(t) == 1:
return True
left = 0
right = len(t) - 1
while left <= right:
if t[left] == t[right]:
left += 1
right -= 1
else:
return False
判断子序列
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
s_len = len(s)
t_len = len(t)
if s_len == 0:
return True
p = 0
for c in t:
if c == s[p]:
p+=1
if p == s_len:
return True
return p == s_len
两数之和
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
left = 0
right = len(numbers) - 1
while left < right:
if numbers[left] + numbers[right] == target:
return [left+1,right+1]
elif numbers[left] + numbers[right] > target:
right -= 1
elif numbers[left] + numbers[right] < target:
left += 1
三数之和
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
length= len(nums)
nums.sort()
res = []
for i in range(length-1):
if i > 0 and nums[i] == nums[i-1]:
continue
elif nums[i] > 0:
break
else:
left = i + 1
right = length - 1
while left < right:
if nums[left] + nums[right] == 0-nums[i]:
res.append([nums[i],nums[left],nums[right]])
left_t = left
while left < right and nums[left] == nums[left_t]:
left += 1
right_t = right
while left < right and nums[right_t] == nums[right]:
right -= 1
elif nums[left] + nums[right] > 0-nums[i]:
right_t = right
while left < right and nums[right_t] == nums[right]:
right -= 1
elif nums[left] + nums[right] < 0-nums[i]:
left_t = left
while left < right and nums[left] == nums[left_t]:
left += 1
return res
盛水最多的容器
class Solution:
def maxArea(self, height: List[int]) -> int:
left = 0
right = len(height) - 1
maxWater = min(height[left], height[right]) * (right - left)
while left < right:
if height[left] < height[right]:
left_t = left
while left < right and height[left] <= height[left_t]:
left += 1
if left < right:
maxWater = max(
maxWater, min(height[left], height[right]) * (right - left)
)
else:
right_t = right
while left < right and height[right_t] >= height[right]:
right -= 1
if left < right:
maxWater = max(
maxWater, min(height[left], height[right]) * (right - left)
)
return maxWater
滑动窗口
长度最小的子数组
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
if sum(nums) < target:
return 0
counter = 0
left = 0
min_len = len(nums)
for right in range(len(nums)):
counter += nums[right]
while counter >= target:
min_len = min(min_len,right-left + 1)
counter -= nums[left]
left += 1
return min_len
无重复的最长字串
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
left = 0
max_len = 1
for right in range(1,len(s)):
if s[right] not in s[left : right]:
max_len = max(max_len, right - left +1)
else:
while s[right] in s[left : right]:
left += 1
return max_len
矩阵
有效的数独
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
def judge_row(i):
map = {key:0 for key in range(10)}
for n in board[i]:
if n != ".":
map[int(n)] += 1
if map[int(n)] > 1:
return False
return True
def judge_col(i):
map = {key:0 for key in range(10)}
for j in range(9):
if board[j][i] != ".":
map[int(board[j][i])] += 1
if map[int(board[j][i])] > 1:
return False
return True
def judge_block(x,y):
map = {key:0 for key in range(10)}
for i in range(3):
for j in range(3):
if board[x+i][y+j] != ".":
print(x+i,y+j)
map[int(board[x+i][y+j])] += 1
if map[int(board[x+i][y+j])] > 1:
return False
return True
for i in range(9):
if not judge_row(i):
return False
for j in range(9):
if not judge_col(j):
return False
for i in range(0,9,3):
for j in range(0,9,3):
if not judge_block(i,j):
return False
return True
螺旋矩阵
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
visited = [[0] * len(matrix[0]) for _ in range(len(matrix))]
res = []
x,y = 0,0
while 0<=x<=len(matrix) - 1 and 0<=y<=len(matrix[0]) - 1 and visited[x][y] == 0:
while y <= len(matrix[0]) - 1 and visited[x][y] == 0:
res.append(matrix[x][y])
visited[x][y] = 1
y+=1
y-=1
x+=1
while x<= len(matrix) - 1 and visited[x][y] == 0:
res.append(matrix[x][y])
visited[x][y] = 1
x+= 1
x-=1
y-=1
while y>=0 and visited[x][y] == 0:
res.append(matrix[x][y])
visited[x][y] = 1
y -= 1
y+=1
x-=1
while x>=0 and visited[x][y] == 0:
res.append(matrix[x][y])
visited[x][y] = 1
x -= 1
x+=1
y+=1
return res
旋转图像
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
m = len(matrix[0])
for i in range(1,n):
for j in range(0,i):
matrix[i][j],matrix[j][i] =matrix[j][i], matrix[i][j]
for i in range(n):
matrix[i] = matrix[i][::-1]
矩阵置零
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
def setZero_Row(x):
for i in range(m):
matrix[x][i] = 0
def setZero_Col(y):
for j in range(n):
matrix[j][y] = 0
n = len(matrix)
m = len(matrix[0])
row = []
col = []
for i in range(n):
for j in range(m):
if matrix[i][j] == 0:
if i not in row:
row.append(i)
if j not in col:
col.append(j)
for r in row:
setZero_Row(r)
for c in col:
setZero_Col(c)
生命游戏
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
n = len(board)
m = len(board[0])
direction = [
[-1, -1],
[-1, 0],
[-1, 1],
[0, -1],
[0, 1],
[1, -1],
[1, 0],
[1, 1],
]
def count(x, y):
counter = 0
for d in direction:
if 0 <= x + d[0] <= n - 1 and 0 <= y + d[1] <= m - 1:
if board[x + d[0]][y + d[1]] == '+':
counter += 1
elif board[x + d[0]][y + d[1]] == '-':
counter += 0
else:
if board[x + d[0]][y + d[1]] > 0:
counter += 1
if board[x][y] == 0:
if counter == 0:
board[x][y] = '-'
else:
board[x][y] = -counter
else:
if counter == 0:
board[x][y] = '+'
else:
board[x][y] = counter
for i in range(n):
for j in range(m):
count(i, j)
print(board)
for x in range(n):
for y in range(m):
if board[x][y] == '+':
origin = 1
counter = 0
elif board[x][y] == '-':
origin = 0
counter = 0
else:
counter = abs(board[x][y])
origin = 1 if board[x][y] >0 else 0
if origin == 1 and counter < 2:
board[x][y] = 0
if origin == 1 and counter == 2 or counter == 3:
board[x][y] = 1
if origin == 1 and counter > 3:
board[x][y] = 0
if origin == 1 and counter == 3:
board[x][y] = 1
for x in range(n):
for y in range(m):
if board[x][y] == '-':
board[x][y] = 0
elif board[x][y] < 0:
board[x][y] = 0
前缀和
和为K的子数组
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
map = {0: 1}
cur_sum = 0
counter = 0
for i in nums:
cur_sum += i
counter += map.get(cur_sum - k, 0)
map[cur_sum] = map.get(cur_sum, 0) + 1
return counter
哈希表
课程表
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
if not prerequisites:
return True
graph = {key:[] for key in range(0,numCourses)}
for pre in prerequisites:
graph[pre[0]].append(pre[1])
queue = []
for key,value in graph.items():
if len(value) == 0:
queue.append(key)
count = 0
while queue:
cur = queue.pop(0)
count += 1
for key,value in graph.items():
if cur in value:
value.remove(cur)
if len(value) == 0:
queue.append(key)
return count == numCourses
链表
反转链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
dummy = ListNode(-1)
dummy.next = head
left_prev = dummy
for i in range(left-1):
left_prev = left_prev.next
left_p = left_prev.next
right_p = dummy
for i in range(right):
right_p = right_p.next
right_next = right_p.next
left_prev.next = right_next
right_p.next = None
for i in range(left,right+1):
left_temp = left_p
left_p = left_p.next
left_temp.next = left_prev.next
left_prev.next = left_temp
return dummy.next
K个一组反转链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
dummy = ListNode(-1)
dummy.next = head
count_node = 0
point = head
while point:
count_node += 1
point = point.next
n = count_node // k
right = dummy
for _ in range(n*k):
right = right.next
dummy.next = right.next
right.next = None
left_prev = dummy
left = head
for _ in range(n):
for _ in range(k):
left_temp = left
left = left.next
left_temp.next = left_prev.next
left_prev.next = left_temp
for _ in range(k):
left_prev = left_prev.next
return dummy.next
旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
# 首先判断头节点是不是为空,或者整个链表只有一个节点
if not head or not head.next:
return head
# 计算链表长度
cur = head
count = 1
while cur.next:
count += 1
cur = cur.next
# 首尾相连
cur.next = head
# 从count-k处断开连接
k = k % count
cur = head
for _ in range(count - k - 1):
cur = cur.next
res = cur.next
cur.next = None
return res
LRU 缓存
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
class LinkListNode:
def __init__(self, key=None, value=None):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.length = 0
self.map = {}
self.head = LinkListNode()
self.tail = LinkListNode()
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key: int) -> int:
if key in self.map:
self.removeNode(self.map[key])
self.addToTail(self.map[key])
return self.map[key].value
else:
return -1
def put(self, key: int, value: int) -> None:
if key in self.map:
self.map[key].value = value
self.removeNode(self.map[key])
self.addToTail(self.map[key])
else:
if self.length >= self.capacity:
self.removeFirst()
else:
self.length += 1
node = LinkListNode(key, value)
self.map[key] = node
self.addToTail(node)
def removeNode(self, node):
node.next.prev = node.prev
node.prev.next = node.next
def addToTail(self, node):
self.tail.prev.next = node
node.prev = self.tail.prev
node.next = self.tail
self.tail.prev = node
def removeFirst(self):
key = self.head.next.key
del self.map[key]
self.head.next.next.prev = self.head
self.head.next = self.head.next.next
两个链表的第一个公共节点
先将两个链表按照最后一个节点对齐,然后从对齐的起点开始同时遍历。
二叉树
翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点
# 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
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def reverse(root):
if not root or (not root.left and not root.right):
return
else:
root.left,root.right = root.right,root.left
reverse(root.left)
reverse(root.right)
reverse(root)
return root
二叉树的层序遍历
给你二叉树的根节点 root ,返回其节点值的层序遍历。 (即逐层地,从左到右访问所有节点)。
# 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
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
queue = [root]
res = []
while queue:
levelSize = len(queue)
res_temp = []
for _ in range(levelSize):
temp = queue.pop(0)
res_temp.append(temp.val)
if temp.left:
queue.append(temp.left)
if temp.right:
queue.append(temp.right)
res.append(res_temp)
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
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
def build(preorder,inorder):
if not preorder:
return None
root = TreeNode(preorder[0])
root_index = inorder.index(preorder[0])
root.left = build(preorder[1:root_index+1],inorder[0:root_index])
root.right = build(preorder[root_index+1:],inorder[root_index+1:])
return root
return build(preorder,inorder)
从中序和后序构造二叉树
# 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
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
def build(inorder,postorder):
if not inorder:
return None
root = TreeNode(postorder[-1])
root_index = inorder.index(postorder[-1])
root.left = build(inorder[0:root_index],postorder[0:root_index])
root.right = build(inorder[root_index+1:],postorder[root_index:-1])
return root
return build(inorder,postorder)
二叉树的最近公共祖先
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
def CommonAncestor(root,p,q):
if root == p or root == q:
return root
left,right = None,None
if root.left:
left = CommonAncestor(root.left,p,q)
if root.right:
right = CommonAncestor(root.right,p,q)
if left and right:
return root
elif left:
return left
else:
return right
return CommonAncestor(root,p,q)
不同的二叉搜索树
class Solution:
def numTrees(self, n):
G = [0]*(n+1)
G[0], G[1] = 1, 1
for i in range(2, n+1):
for j in range(1, i+1):
G[i] += G[j-1] * G[i-j]
return G[n]
不同的二叉搜索树II
# 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
class Solution:
def generateTrees(self, n: int) -> List[Optional[TreeNode]]:
if n==0:
return None
def move(tree,offset):
if tree == None:
return None
else:
new_tree = TreeNode(tree.val + offset)
new_tree.left = move(tree.left,offset)
new_tree.right = move(tree.right,offset)
return new_tree
# 设置dp
dp = [[] for _ in range(n+1)]
dp[0].append(None)
for i in range(1,n+1):
for j in range(0,i):
for left in dp[j]:
for right in dp[i-j-1]:
root = TreeNode(j+1)
root.left = left
root.right = move(right,j+1)
print(root)
dp[i].append(root)
return dp[n]
栈
最小栈(最大栈同理)
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
class MinStack:
def __init__(self):
self.stack = []
self.min_stack = []
def push(self, val: int) -> None:
self.stack.append(val)
if not self.min_stack:
self.min_stack.append(val)
elif val <= self.min_stack[-1]:
self.min_stack.append(val)
def pop(self) -> None:
t = self.stack.pop(-1)
if t == self.min_stack[-1]:
self.min_stack.pop(-1)
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.min_stack[-1]
有效的括号
class Solution:
def isValid(self, s: str) -> bool:
stack= []
for c in s:
if not stack or (c == '(' or c == '[' or c == '{'):
stack.append(c)
else:
if c == ')' and stack[-1] == '(':
stack.pop(-1)
if c == ']' and stack[-1] == '[':
stack.pop(-1)
if c == '}' and stack[-1] == '{':
stack.pop(-1)
if not stack:
return True
return False
一维动态规划
爬楼梯
Leetcode 70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
class Solution:
def climbStairs(self, n: int) -> int:
dp = [1]*n
dp[0] = 1
dp[1] = 2
for i in range(2,len(dp)):
dp[i] = dp[i-1] + dp[i-2]
return dp[-1]
最大子数组和
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
for i in range(1, n):
nums[i] = max(nums[i], nums[i] + nums[i - 1])
return max(nums)
打家劫舍
Leetcode 198. 打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
class Solution:
def rob(self, nums: List[int]) -> int:
dp = nums
for i in range(len(nums)):
if i-2>=0:
dp[i] += dp[i-2]
return max(dp)
最长递增子序列
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
def bin(nums,target):
left = 0
right = len(nums)-1
res = -1
while left <= right:
mid = (left+right)//2
if nums[mid]<target:
left = mid+1
else:
res = mid
right = mid - 1
return res
queue = [nums[0]]
for i in range(1,len(nums)):
if nums[i]>queue[-1]:
queue.append(nums[i])
else:
index = bin(queue,nums[i])
queue[index] = nums[i]
return len(queue)
二维动态规划
最长公共子序列
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
n = len(text1)
m = len(text2)
dp = [[0]*(m+1) for _ in range(n+1)]
for i in range(1,n+1):
for j in range(1,m+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[-1][-1]
三角形最小路径和
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
n = len(triangle)
if n<=1:
return triangle[0][0]
triangle[1][0] += triangle[0][0]
triangle[1][1] += triangle[0][0]
for i in range(2, n):
m = len(triangle[i])
for j in range(m):
if j == m - 1:
triangle[i][j] += triangle[i - 1][j - 1]
elif j == 0:
triangle[i][j] += triangle[i - 1][j]
else:
triangle[i][j] += min(triangle[i - 1][j - 1], triangle[i - 1][j])
return min(triangle[-1])
编辑距离
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m = len(word1)
n = len(word2)
dp = [[i+j for i in range(n+1)] for j in range(m+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][j-1],dp[i-1][j],dp[i-1][j-1]) + 1
return dp[-1][-1]
最小路径和
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
n = len(grid)
m = len(grid[0])
for i in range(1,m):
grid[0][i] += grid[0][i-1]
for i in range(1,n):
grid[i][0] += grid[i-1][0]
for i in range(1,n):
for j in range(1,m):
grid[i][j] += min(grid[i-1][j],grid[i][j-1])
return grid[-1][-1]
不同路径
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
n = len(obstacleGrid)
m = len(obstacleGrid[0])
dp = [[0] * m for _ in range(n)]
if obstacleGrid[0][0] == 0:
dp[0][0] = 1
else:
dp[0][0] = 0
if m>=1:
for i in range(1, m):
dp[0][i] = dp[0][i - 1] if obstacleGrid[0][i] != 1 else 0
if n>=1:
for j in range(1, n):
dp[j][0] = dp[j - 1][0] if obstacleGrid[j][0] != 1 else 0
if n>=1 and m>=1:
for i in range(1, n):
for j in range(1, m):
if obstacleGrid[i][j] != 1:
left = dp[i][j - 1] if obstacleGrid[i][j - 1] != 1 else 0
up = dp[i - 1][j] if obstacleGrid[i - 1][j] != 1 else 0
dp[i][j] = left + up
return dp[-1][-1]
最长回文子串
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
counter = 0
res = ""
i = 0
while i < n:
left = math.floor(i)
right = math.ceil(i)
while left >= 0 and right < n and s[left] == s[right]:
if right - left + 1 > counter:
counter = right - left + 1
res = s[left:right + 1]
left -= 1
right += 1
i += 0.5
return res
交错字符串
class Solution:
def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
n = len(s1)
m = len(s2)
if n+m != len(s3):
return False
dp = [[False] * (m + 1) for _ in range(n + 1)]
dp[0][0] = True
for i in range(1, m + 1):
dp[0][i] = dp[0][i - 1] and s2[i - 1] == s3[i - 1]
for j in range(1, n + 1):
dp[j][0] = dp[j - 1][0] and s1[j - 1] == s3[j - 1]
for i in range(1, n + 1):
for j in range(1, m + 1):
dp[i][j] = (dp[i][j - 1] and s2[j - 1] == s3[i + j - 1]) or \
(dp[i - 1][j] and s1[i - 1] == s3[i + j - 1])
return dp[-1][-1]
买卖股票的最佳时机
class Solution:
def maxProfit(self, prices: List[int]) -> int:
min_price = prices[0]
max_profit = 0
for p in prices:
max_profit = max(max_profit,p-min_price)
min_price = min(min_price,p)
return max_profit
买卖股票的最佳时机II
class Solution:
def maxProfit(self, prices: List[int]) -> int:
m = len(prices)
dp = [[0]*m for _ in range(2)]
dp[0][0] = -prices[0]
dp[1][0] = 0
for i in range(1,m):
dp[0][i] = max(dp[0][i-1],dp[1][i-1]-prices[i])
dp[1][i] = max(dp[0][i-1]+prices[i],dp[1][i-1])
return max(dp[0][-1],dp[1][-1])
买卖股票的最佳时机III
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
dp = [[[0, 0] for i in range(3)] for j in range(n)]
for j in range(1, 3):
dp[0][j][1] = -prices[0]
for i in range(1, n):
for j in range(1, 3):
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i])
dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i])
return dp[-1][-1][0]
买卖股票的最佳时机IV
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
n = len(prices)
if k >= n // 2:
res = 0
for i in range(1, n):
if prices[i] > prices[i - 1]:
res += prices[i] - prices[i - 1]
return res
else:
dp = [[[0, 0] for i in range(k+1)] for j in range(n)]
for i in range(1, k+1):
dp[0][i][1] = -prices[0]
for i in range(1, n):
for j in range(1, k+1):
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i])
dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i])
return dp[-1][-1][0]
最大正方形
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
n = len(matrix)
m = len(matrix[0])
dp = [[0] * (m + 1) for _ in range(n + 1)]
max_size = 0
for i in range(1, n+1):
for j in range(1, m+1):
if matrix[i - 1][j - 1] == '1':
dp[i][j] = min(dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]) + 1
max_size = max(max_size, dp[i][j])
return max_size*max_size
通配符匹配
通配符匹配II
# def is_match(s, p):
# # Initialize DP table with False
# dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
# # Base case: empty pattern matches empty string
# dp[0][0] = True
# # Handle patterns like "*", "?", "*a", "?a" etc. at the start
# for j in range(1, len(p) + 1):
# if p[j - 1] == '*':
# dp[0][j] = dp[0][j - 2]
# elif p[j - 1] == '?':
# dp[0][j] = dp[0][j - 1]
# for d in dp:
# print(d)
# # Fill the DP table
# for i in range(1, len(s) + 1):
# for j in range(1, len(p) + 1):
# if p[j - 1] == '*':
# dp[i][j] = dp[i][j - 2] or (dp[i - 1][j] and (p[j - 2] == s[i - 1] or p[j - 2] == '.'))
# elif p[j - 1] == '?':
# dp[i][j] = dp[i][j - 2] or (dp[i - 1][j - 1] and (p[j - 2] == s[i - 1] or p[j - 2] == '.'))
# elif p[j - 1] == '.' or p[j - 1] == s[i - 1]:
# dp[i][j] = dp[i - 1][j - 1]
# for d in dp:
# print(d)
# return dp[len(s)][len(p)]
# # # 示例测试
# # s = "aab"
# # p = "c*a*b"
# # print(is_match(s, p)) # 输出: True
# # s = "mississippi"
# # p = "mis*is*p*."
# # print(is_match(s, p)) # 输出: False
# s = "aa"
# p = "a*"
# print(is_match(s, p)) # 输出: True
# # s = "aa"
# # p = "a*"
# # print(is_match(s, p)) # 输出: True
# # s = "aab"
# # p = "c*a*b?"
# # print(is_match(s, p)) # 输出: True
# # s = "aab"
# # p = "a*b?"
# # print(is_match(s, p)) # 输出: True
# # s = "aab"
# # p = ".*b?"
# # print(is_match(s, p)) # 输出: True
# # s = "aab"
# # p = "a?b?"
# # print(is_match(s, p)) # 输出: True
# # s = "aab"
# # p = "a?b"
# # print(is_match(s, p)) # 输出: False
回溯
电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if not digits:
return []
length = len(digits)
map = {
"2":['a','b','c'],
"3":['d','e','f'],
"4":['g','h','i'],
"5":['j','k','l'],
"6":['m','n','o'],
"7":['p','q','r','s'],
"8":['t','u','v'],
"9":['w','x','y','z']
}
res = []
def dfs(s,index):
if index == length:
res.append(s)
return
for c in map[digits[index]]:
t = s+c
dfs(t,index + 1)
dfs("",0)
return res
分割回文串
class Solution:
def partition(self, s: str) -> List[List[str]]:
n = len(s)
ret = list()
ans = list()
@cache
def isPalindrome(i: int, j: int) -> int:
if i >= j:
return 1
return isPalindrome(i + 1, j - 1) if s[i] == s[j] else -1
def dfs(i: int):
if i == n:
ret.append(ans[:])
return
for j in range(i, n):
if isPalindrome(i, j) == 1:
ans.append(s[i:j+1])
dfs(j + 1)
ans.pop()
dfs(0)
isPalindrome.cache_clear()
return ret
组合
所有可能组合
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
res = []
def dfs(nums,index,n,k):
if len(nums) == k:
res.append(nums[:])
return
for i in range(index+1,n+1):
temp = nums[:]
temp.append(i)
dfs(temp,index+i,n,k)
dfs([],0,n,k)
return res
全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
length = len(nums)
res = []
def dfs(nums,start,length):
if start == length-1:
res.append(nums[:])
for i in range(start,length):
nums[start],nums[i] = nums[i],nums[start]
dfs(nums,start+1,length)
nums[i],nums[start] = nums[start],nums[i]
dfs(nums,0,length)
return res
组合总和
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
length = len(candidates)
res = []
def dfs(nums, index, sum):
if sum == target:
res.append(nums[:])
return
for j in range(index,length):
if sum + candidates[j] > target:
return
if sum + candidates[j] <= target:
t = nums[:]
t.append(candidates[j])
dfs(t, j, sum + candidates[j])
dfs([], 0, 0)
return res
二分
二分法的几个位置
nums = [1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 8, 9]
n = len(nums)
left = 0
right = n - 1
result = -1
target = 5
while left <= right:
mid = (left + right) // 2
if nums[mid] < target:
result = mid
left = mid + 1
else:
right = mid - 1
print(result, nums[result])
left = 0
right = n - 1
result = -1
target = 5
while left <= right:
mid = (left + right) // 2
if nums[mid] > target:
result = mid
right = mid - 1
else:
left = mid + 1
print(result, nums[result])
left = 0
right = n - 1
result = -1
target = 5
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
result = mid
right = mid - 1
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
print(result, nums[result])
left = 0
right = n - 1
result = -1
target = 5
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
result = mid
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
print(result, nums[result])
旋转数组
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while left <= right:
mid = (left+right)//2
if nums[mid] == target:
return mid
if nums[mid]>=nums[left]:
if nums[left]<=target<=nums[mid]:
right -= 1
else:
left += 1
else:
if nums[mid]<=target<=nums[right]:
left += 1
else:
right -= 1
return -1
第K个缺失的正整数
class Solution:
def findKthPositive(self, arr: List[int], k: int) -> int:
n = len(arr)
left = 0
right = n - 1
while left <= right:
mid = (left + right) // 2
miss = arr[mid] - mid - 1
if miss < k:
left = mid + 1
else:
right = mid - 1
return left + k
TopK
第k个元素
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def topK(nums, k):
left, mid, right = partition(nums)
left_length = len(left)
mid_length = len(mid)
right_length = len(right)
if right_length >= k:
return topK(right, k)
elif k > right_length and k <= right_length + mid_length:
return mid[0]
elif k > right_length + mid_length:
return topK(left, k - right_length - mid_length)
def partition(arr):
if not arr:
return [], [], []
select = random.choice(arr)
left,mid,right = [],[],[]
for n in arr:
if n < select:
left.append(n)
elif n == select:
mid.append(n)
elif n > select:
right.append(n)
return left, mid, right
return topK(nums,k)
前k个元素
class Solution:
def smallestK(self, arr: List[int], k: int) -> List[int]:
def top(arr,k):
left,mid,right = partition(arr)
left_length = len(left)
mid_length = len(mid)
if left_length >= k:
return top(left,k)
elif k>left_length and k<= left_length+mid_length:
return left + mid[:k-left_length]
elif k>left_length + mid_length:
return left+mid+top(right,k-left_length-mid_length)
def partition(arr):
if not arr:
return [],[],[]
select = random.choice(arr)
left,mid,right = [],[],[]
for value in arr:
if value < select:
left.append(value)
elif value == select:
mid.append(value)
elif value > select:
right.append(value)
return left,mid,right
if k == 0:
return []
return top(arr,k)
环
判断是否有环
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if not head:
return False
fast = head
slow = head
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
return False
找到环的起点
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if not head:
return False
fast = head
slow = head
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
fast = head
while fast != slow:
fast = fast.next
slow = slow.next
return fast
return False
单调队列
最长递增子序列
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
def binaraysearch(queue,target):
left = 0
right = len(queue) - 1
res = -1
while left <= right:
mid = (left+right) // 2
if queue[mid] >= target:
res = mid
right -= 1
else:
left += 1
return res
queue = [nums[0]]
for i in range(1,len(nums)):
if nums[i] > queue[-1]:
queue.append(nums[i])
else:
index = binaraysearch(queue,nums[i])
queue[index] = nums[i]
return len(queue)
滑动窗口的最大值
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if k == 1:
return nums
queue = [[0,nums[0]]]
res = []
for i in range(1,len(nums)):
while queue and queue[-1][1] < nums[i]:
queue.pop(-1)
queue.append([i,nums[i]])
while i - queue[0][0]>= k:
queue.pop(0)
if i >= k-1:
res.append(queue[0][1])
return res
排序
排序数组
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def quicksort(nums):
if not nums:
return []
pivot = random.choice(nums)
less = []
equal = []
bigger = []
for n in nums:
if n < pivot:
less.append(n)
if n == pivot:
equal.append(n)
if n> pivot:
bigger.append(n)
return quicksort(less) + equal + quicksort(bigger)
return quicksort(nums)
排序链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def find_mid(head):
dummy = ListNode(-1)
dummy.next = head
slow_pre = dummy
fast = head
slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
slow_pre = slow_pre.next
if fast and fast.next:
slow = slow.next
slow_pre = slow_pre.next
slow_pre.next = None
return slow
def merge(head1, head2):
dummy = ListNode(-1)
cur = dummy
while head1 and head2:
if head1.val <= head2.val:
cur.next = head1
head1 = head1.next
elif head2.val <= head1.val:
cur.next = head2
head2 = head2.next
cur = cur.next
if head1:
cur.next = head1
if head2:
cur.next = head2
return dummy.next
def sort(head):
mid = find_mid(head)
if not head.next and not mid.next:
return merge(head, mid)
elif not head.next:
return merge(head, sort(mid))
elif not mid.next:
return merge(sort(head), mid)
else:
return merge(sort(head), sort(mid))
if not head or not head.next:
return head
return sort(head)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义