左右边界
int left_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
// 搜索区间为 [left, right]
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
// 搜索区间变为 [mid+1, right]
left = mid + 1;
} else if (nums[mid] > target) {
// 搜索区间变为 [left, mid-1]
right = mid - 1;
} else if (nums[mid] == target) {
// 收缩右侧边界
right = mid - 1;
}
}
// 检查出界情况
if (left >= nums.length || nums[left] != target) {
return -1;
}
return left;
}
int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 这里改成收缩左侧边界即可
left = mid + 1;
}
}
// 这里改为检查 right 越界的情况,见下图
if (right < 0 || nums[right] != target) {
return -1;
}
return right;
}
比目标值大的最右边界
def get_target(nums,target):
if len(nums) == 0 : return -1
if target < nums[0]:
return 0
if target > nums[-1]:
return -1
left = 0
right = len(nums)
while left < right:
mid = left + (right-left) // 2
if nums[mid] == target:
left = mid + 1
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid
res = left-1 if left != 0 and nums[left-1] == target else left
return res
滑动窗口最大值
def maxSlidingWindow(nums,k):
if not nums or k == 0:return []
deque = collections.deque()
for i in range(k):
while deque and deque[-1] < nums[i]:
deque.pop()
deque.append(nums[i])
res = [deque[0]]
for i in range(k,len(nums)):
if deque[0] == nums[i-k]:
deque.popleft()
while deque and deque[-1] < nums[i]:
deque.pop()
deque.append(nums[i])
res.append(deque[0])
return res
排序数组查找第一个位置和最后一个位置
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
leftindex = self.binary(nums,target,True)
rightindex = self.binary(nums,target,False)-1
if leftindex <= rightindex and rightindex < len(nums) and nums[leftindex] == target and nums[rightindex] == target:
return [leftindex,rightindex]
return [-1,-1]
def binary(self,nums,target,lower):
left = 0
right = len(nums)-1
ans = len(nums)
while left <= right:
mid =(left + right) // 2
if (nums[mid] > target) or (lower and nums[mid] >= target):
right = mid - 1
ans = mid
else:
left = mid + 1
return ans
快速排序
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def quick_sort(start,end):
if start >= end : return
idx = random.randint(start,end)
nums[start],nums[idx] = nums[idx],nums[start]
privor = nums[start]
l,r = start,end
while l < r:
while l < r and nums[r] >= privor:
r -= 1
while l < r and nums[l] <= privor:
l += 1
nums[l],nums[r] = nums[r],nums[l]
nums[start],nums[l] = nums[l],nums[start]
quick_sort(start,l-1)
quick_sort(l+1,end)
quick_sort(0,len(nums)-1)
return nums
无重复最长子串
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
setc = set()
n = len(s)
rk = -1
ans = 0
for i in range(n):
if i != 0:
setc.remove(s[i-1])
while rk + 1 < n and s[rk + 1] not in setc:
setc.add(s[rk+1])
rk += 1
ans = max(ans,rk-i+1)
return ans
迭代实现中序遍历
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
# res = []
# def dfs(root):
# if not root:
# return
# dfs(root.left)
# res.append(root.val)
# dfs(root.right)
# dfs(root)
# return res
stack,rst = [root],[]
while stack:
i = stack.pop()
if isinstance(i,TreeNode):
stack.extend([i.right,i.val,i.left])
elif isinstance(i,int):
rst.append(i)
return rst
矩阵最大路径和
合并2个有序数组
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.
"""
sorted = []
p1,p2 = 0,0
while p1 < m or p2 < n:
if p1 == m:
sorted.append(nums2[p2])
p2 += 1
elif p2 == n:
sorted.append(nums1[p1])
p1 += 1
elif nums1[p1] < nums2[p2]:
sorted.append(nums1[p1])
p1 += 1
else:
sorted.append(nums2[p2])
p2 += 1
nums1[:] = sorted
合并2个有序链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
cur = dum = ListNode(0)
while l1 and l2:
if l1.val < l2.val:
cur.next,l1 = l1,l1.next
else:
cur.next,l2 = l2,l2.next
cur = cur.next
cur.next = l1 if l1 else l2
return dum.next
合并n个有序数组
合并n个有序链表
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
import heapq
dummy = ListNode(0)
p = dummy
head = []
for i in range(len(lists)):
if lists[i] :
heapq.heappush(head, (lists[i].val, i))
lists[i] = lists[i].next
while head:
val, idx = heapq.heappop(head)
p.next = ListNode(val)
p = p.next
if lists[idx]:
heapq.heappush(head, (lists[idx].val, idx))
lists[idx] = lists[idx].next
return dummy.next
第k大数
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def partition(nums,l,r):
privot = nums[r]
i = l-1
for j in range(l,r):
if nums[j] >= privot:
i += 1
nums[i],nums[j] = nums[j],nums[i]
nums[i+1],nums[r] = nums[r],nums[i+1]
return i+1
l = 0
r = len(nums) -1
while True:
privot_index = partition(nums,l,r)
if privot_index == k-1:return nums[k-1]
elif privot_index < k-1:
l = privot_index + 1
else:
r = privot_index -1
有序矩阵中第 K 小的元素
class Solution:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
n = len(matrix)
def check(mid):
i,j = n-1,0
num = 0
while i >= 0 and j < n:
if matrix[i][j] <= mid:
num += i + 1
j += 1
else:
i -= 1
return num >= k
left,right = matrix[0][0],matrix[-1][-1]
while left < right:
mid = (left + right) // 2
if check(mid):
right = mid
else:
left = mid + 1
return left
两数之和
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
t_dict = {}
for i,num in enumerate(nums):
if num in t_dict:
return [t_dict[num],i]
t_dict[target-num] = i
return []
三数之和
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
res = []
if n < 3:
return []
nums.sort()
for i in range(n):
if nums[i] > 0: return res
if i > 0 and nums[i] == nums[i-1]:continue
L = i+1
R = n - 1
while L < R:
if nums[i] + nums[L] + nums[R] == 0:
res.append([nums[i],nums[L],nums[R]])
while L < R and nums[L] == nums[L+1]:
L += 1
while L < R and nums[R] == nums[R - 1]:
R -= 1
L += 1
R -= 1
elif nums[i] + nums[L] + nums[R] > 0:
R -= 1
else:
L += 1
return res
灯泡开关
数组中超过一半的数字
class Solution:
def majorityElement(self, nums: List[int]) -> int:
votes = 0
for num in nums:
if votes == 0:x = num
if x == num : votes += 1
else : votes -= 1
return x
树的深度遍历
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root : return 0
return max(self.maxDepth(root.left),self.maxDepth(root.right)) + 1
二叉树前序遍历
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack,rst = [root],[]
while stack:
i = stack.pop()
if isinstance(i,TreeNode):
stack.extend([i.right,i.left,i.val])
elif isinstance(i,int):
rst.append(i)
return rst
链表m到n位置反转
class Solution(object):
def reverseBetween(self, head, left, right):
count = 1
dummy = ListNode(0)
dummy.next = head
pre = dummy
while pre.next and count < left:
pre = pre.next
count += 1
cur = pre.next
tail = cur
while cur and count <= right:
nxt = cur.next
cur.next = pre.next
pre.next = cur
tail.next = nxt
cur = nxt
count += 1
return dummy.next
最小栈
import math
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.min_stack = [math.inf]
def push(self, x: int) -> None:
self.stack.append(x)
self.min_stack.append(min(x,self.min_stack[-1]))
def pop(self) -> None:
self.stack.pop()
self.min_stack.pop()
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.min_stack[-1]
盛水最多的容器
def maxArea(height):
l,r = 0,len(higth)-1
ans = 0
while l < r:
area = min(height[l],height[r]) * (r-l)
ans = max(area,ans)
if height[l] < height[r]:
l += 1
else:
r -= 1
return ans
有序数组中目标值出现的次数
接雨水
去除重复字母
class Solution:
def removeDuplicateLetters(self, s) -> int:
stack = []
remain_counter = collections.Counter(s)
for c in s:
if c not in stack:
while stack and c < stack[-1] and remain_counter[stack[-1]] > 0:
stack.pop()
stack.append(c)
remain_counter[c] -= 1
return ''.join(stack)
实现根号
class Solution:
def mySqrt(self, x: int) -> int:
left = 0
right = x
ans = -1
while left <= right:
mid = left + (right - left) // 2
if mid ** 2 <= x:
ans = mid
left = mid + 1
else:
right = mid - 1
return ans
先序遍历+中序遍历 生成后序遍历
先序遍历+中序遍历 构造二叉树
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def myBuildTree(preorder_left,preorder_right,inorder_left,inorder_right):
if preorder_left > preorder_right:
return None
preorder_root = preorder_left
inorder_root = index[preorder[preorder_root]]
root = TreeNode(preorder[preorder_root])
size_left_subtree = inorder_root - inorder_left
root.left = myBuildTree(preorder_left + 1,preorder_left + size_left_subtree,inorder_left, inorder_root - 1)
root.right = myBuildTree(preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right)
return root
n = len(preorder)
index = {element: i for i,element in enumerate(inorder)}
return myBuildTree(0,n-1,0,n-1)
搜索旋转排序数组
class Solution:
def search(self, nums: List[int], target: int) -> int:
lo,hi = 0,len(nums)-1
while lo <= hi:
mid = lo+(hi - lo) // 2
if nums[mid] == target:
return mid
elif nums[lo] <= nums[mid]:
if nums[lo] <= target and target < nums[mid]:
hi = mid - 1
else:
lo = mid + 1
else:
if nums[mid] < target and target <= nums[hi]:
lo = mid + 1
else:
hi = mid - 1
return -1
最长公共子序列
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
m,n = len(text1),len(text2)
dp = [[0] * ( n+ 1) for _ in range(m + 1)]
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])
return dp[-1][-1]
旋转数组
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return list()
rows, columns = len(matrix), len(matrix[0])
order = list()
left, right, top, bottom = 0, columns - 1, 0, rows - 1
while left <= right and top <= bottom:
for column in range(left, right + 1):
order.append(matrix[top][column])
for row in range(top + 1, bottom + 1):
order.append(matrix[row][right])
if left < right and top < bottom:
for column in range(right - 1, left, -1):
order.append(matrix[bottom][column])
for row in range(bottom, top, -1):
order.append(matrix[row][left])
left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1
return order
字符串的正则表达式
cache缓存
class DLinkedNode:
def __init__(self,key=0,value=0):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.cache = dict()
self.head = DLinkedNode()
self.tail = DLinkedNode()
self.head.next = self.tail
self.tail.prev = self.head
self.capacity = capacity
self.size = 0
def get(self, key: int) -> int:
if key not in self.cache:
return -1
node = self.cache[key]
self.moveToHead(node)
return node.value
def put(self, key: int, value: int) -> None:
if key not in self.cache:
node = DLinkedNode(key,value)
self.cache[key] = node
self.addToHead(node)
self.size += 1
if self.size > self.capacity:
removed = self.removeTail()
self.cache.pop(removed.key)
self.size -= 1
else:
node = self.cache[key]
node.value = value
self.moveToHead(node)
def addToHead(self,node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def removeNode(self,node):
node.prev.next = node.next
node.next.prev = node.prev
def moveToHead(self,node):
self.removeNode(node)
self.addToHead(node)
def removeTail(self):
node = self.tail.prev
self.removeNode(node)
return node
k个一组翻转链表
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
def reverse(head):
pre = None
cur = head
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
dum = ListNode(0)
dum.next = head
pre,end = dum,dum
while end.next :
for i in range(k):
if end:
end = end.next
if not end:break
start = pre.next
next1 = end.next
end.next = None
pre.next = reverse(start)
start.next = next1
pre = start
end = pre
最长连续子序列
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
# dp = [0] * len(nums)
# dp[0] = nums[0]
# for i in range(1,len(nums)):
# if dp[i-1] > 0:
# dp[i] = dp[i-1] + nums[i]
# else:
# dp[i] = nums[i]
# return max(dp)
sum_v = nums[0]
max_v = nums[0]
for i in range(1,len(nums)):
if sum_v > 0:
sum_v += nums[i]
else:
sum_v = nums[i]
max_v = max(max_v,sum_v)
return max_v
最长递增子序列
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums: return 0
dp = [1] * len(nums)
for i in range (len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i],dp[j] + 1)
return max(dp)
树左叶子到右叶子节点的最大路径和
class Solution:
def __init__(self):
self.maxSum = float("-inf")
def maxPathSum(self, root: TreeNode) -> int:
def maxGain(node):
if not node:
return 0
# 递归计算左右子节点的最大贡献值
# 只有在最大贡献值大于 0 时,才会选取对应子节点
leftGain = max(maxGain(node.left), 0)
rightGain = max(maxGain(node.right), 0)
# 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
priceNewpath = node.val + leftGain + rightGain
# 更新答案
self.maxSum = max(self.maxSum, priceNewpath)
# 返回节点的最大贡献值
return node.val + max(leftGain, rightGain)
maxGain(root)
最长回文子串
class Solution:
def aroundCenter(self,s,left,right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return left + 1 , right - 1
def longestPalindrome(self, s: str) -> str:
start,end = 0,0
for i in range(len(s)):
left1,right1 = self.aroundCenter(s,i,i)
left2,right2 = self.aroundCenter(s,i,i+1)
if right1 - left1 > end - start:
start,end = left1,right1
if right2 - left2 > end - start:
start,end = left2,right2
return s[start:end+1]
最小高度二叉树
组合总和2
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
def dfs(begin,path,residue):
if residue == 0:
res.append(path[:])
return
for index in range(begin,size):
if candidates[index] > residue:
break
if index > begin and candidates[index - 1] == candidates[index]:
continue
path.append(candidates[index])
dfs(index+1,path,residue - candidates[index])
path.pop()
size = len(candidates)
if size == 0:
return []
candidates.sort()
res = []
dfs(0,[],target)
return res
岛屿数量
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
def dfs(grid,i,j):
if not 0 <= i < len(grid) or not 0 <= j < len(grid[0]) or grid[i][j] == '0':return
grid[i][j] = '0'
dfs(grid,i+1,j)
dfs(grid,i-1,j)
dfs(grid,i,j+1)
dfs(grid,i,j-1)
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1':
dfs(grid,i,j)
count +=1
return count
编辑距离
# 编辑距离
def minDistance(self, word1: str, word2: str) -> int:
n1 = len(word1)
n2 = len(word2)
dp = [[0] * (n2+1) for _ in range(n1 + 1)]
for i in range(1,n1 + 1):
dp[i][0] = dp[i-1][0] + 1
for j in range(1,n2 + 1):
dp[0][j] = dp[0][j-1] + 1
for i in range(1,n1 + 1):
for j in range(1,n2 + 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],dp[i][j-1],dp[i-1][j-1]) + 1
return dp[-1][-1]