defevaluate_expression(expression): """使用栈计算中缀表达式""" defprecedence(op): if op in'+-': return1 if op in'*/': return2 return0 defapply_operator(values, operators): right = values.pop() left = values.pop() op = operators.pop() if op == '+': values.append(left + right) elif op == '-': values.append(left - right) elif op == '*': values.append(left * right) elif op == '/': values.append(left / right) values = [] operators = [] i = 0 while i < len(expression): if expression[i] == ' ': i += 1 continue if expression[i].isdigit(): num = 0 while i < len(expression) and expression[i].isdigit(): num = num * 10 + int(expression[i]) i += 1 values.append(num) continue if expression[i] == '(': operators.append(expression[i]) elif expression[i] == ')': while operators and operators[-1] != '(': apply_operator(values, operators) operators.pop() else: while operators and precedence(operators[-1]) >= precedence(expression[i]): apply_operator(values, operators) operators.append(expression[i]) i += 1 while operators: apply_operator(values, operators) return values[0] if values else0
2. 括号匹配
1 2 3 4 5 6 7 8 9 10 11 12 13
defis_valid_parentheses(s): """判断括号是否匹配""" stack = [] mapping = {')': '(', ']': '[', '}': '{'} for char in s: if char in mapping: ifnot stack or stack.pop() != mapping[char]: returnFalse else: stack.append(char) returnlen(stack) == 0
definfix_to_postfix(expression): """将中缀表达式转换为后缀表达式""" defprecedence(op): if op in'+-': return1 if op in'*/': return2 return0 result = [] stack = [] for char in expression: if char.isdigit() or char.isalpha(): result.append(char) elif char == '(': stack.append(char) elif char == ')': while stack and stack[-1] != '(': result.append(stack.pop()) stack.pop() else: while stack and stack[-1] != '('and precedence(stack[-1]) >= precedence(char): result.append(stack.pop()) stack.append(char) while stack: result.append(stack.pop()) return''.join(result)
defnext_greater_element(nums): """找出每个元素右边第一个比它大的元素""" result = [-1] * len(nums) stack = [] # 存储索引,保持单调递减 for i inrange(len(nums)): while stack and nums[stack[-1]] < nums[i]: index = stack.pop() result[index] = nums[i] stack.append(i) return result
defnext_smaller_element(nums): """找出每个元素右边第一个比它小的元素""" result = [-1] * len(nums) stack = [] # 存储索引,保持单调递增 for i inrange(len(nums)): while stack and nums[stack[-1]] > nums[i]: index = stack.pop() result[index] = nums[i] stack.append(i) return result
deflevel_order_traversal(root): ifnot root: return [] result = [] queue = [root] while queue: level = [] size = len(queue) for _ inrange(size): node = queue.pop(0) level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level) return result
2. BFS(广度优先搜索)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
defbfs(graph, start): """图的广度优先搜索""" visited = set() queue = [start] result = [] while queue: node = queue.pop(0) if node notin visited: visited.add(node) result.append(node) for neighbor in graph[node]: if neighbor notin visited: queue.append(neighbor) return result
defmax_sliding_window(nums, k): """使用双端队列实现滑动窗口最大值""" ifnot nums or k == 0: return [] deque_obj = [] result = [] for i inrange(len(nums)): # 移除窗口外的元素 while deque_obj and deque_obj[0] < i - k + 1: deque_obj.pop(0) # 移除小于当前元素的元素(保持单调递减) while deque_obj and nums[deque_obj[-1]] < nums[i]: deque_obj.pop() deque_obj.append(i) # 窗口形成后,记录最大值 if i >= k - 1: result.append(nums[deque_obj[0]]) return result
排序算法
排序算法分类
按稳定性分类:
稳定排序:相同元素在排序后的相对位置不变(冒泡、插入、归并、计数、基数)
不稳定排序:相同元素在排序后的相对位置可能改变(选择、快速、堆)
按时间复杂度分类:
**O(n²)**:冒泡、选择、插入
**O(n log n)**:快速、归并、堆
**O(n)**:计数、基数、桶
按空间复杂度分类:
原地排序:O(1)(冒泡、选择、插入、快速、堆)
非原地排序:O(n)(归并、计数、基数、桶)
冒泡排序(Bubble Sort)
原理: 重复遍历数组,比较相邻元素,如果顺序错误就交换。
时间复杂度: O(n²) 空间复杂度: O(1) 稳定性: 稳定
1 2 3 4 5 6 7 8 9 10 11 12
defbubble_sort(arr): n = len(arr) for i inrange(n): swapped = False for j inrange(0, n - i - 1): if arr[j] > arr[j + 1]: arr[j], arr[j + 1] = arr[j + 1], arr[j] swapped = True # 如果没有交换,说明已经有序 ifnot swapped: break return arr
优化版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defbubble_sort_optimized(arr): n = len(arr) for i inrange(n): swapped = False last_swap = n - 1 for j inrange(0, n - i - 1): if arr[j] > arr[j + 1]: arr[j], arr[j + 1] = arr[j + 1], arr[j] swapped = True last_swap = j ifnot swapped: break n = last_swap + 1 return arr
选择排序(Selection Sort)
原理: 每次找到未排序部分的最小元素,放到已排序部分的末尾。
时间复杂度: O(n²) 空间复杂度: O(1) 稳定性: 不稳定
1 2 3 4 5 6 7 8 9
defselection_sort(arr): n = len(arr) for i inrange(n): min_idx = i for j inrange(i + 1, n): if arr[j] < arr[min_idx]: min_idx = j arr[i], arr[min_idx] = arr[min_idx], arr[i] return arr
插入排序(Insertion Sort)
原理: 将元素逐个插入到已排序部分的正确位置。
时间复杂度: O(n²),最好情况 O(n) 空间复杂度: O(1) 稳定性: 稳定
1 2 3 4 5 6 7 8 9
definsertion_sort(arr): for i inrange(1, len(arr)): key = arr[i] j = i - 1 while j >= 0and arr[j] > key: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = key return arr
defquick_sort(arr, low=0, high=None): if high isNone: high = len(arr) - 1 if low < high: pi = partition(arr, low, high) quick_sort(arr, low, pi - 1) quick_sort(arr, pi + 1, high) return arr
defpartition(arr, low, high): pivot = arr[high] i = low - 1 for j inrange(low, high): if arr[j] < pivot: i += 1 arr[i], arr[j] = arr[j], arr[i] arr[i + 1], arr[high] = arr[high], arr[i + 1] return i + 1
defmerge_sort(arr): iflen(arr) <= 1: return arr mid = len(arr) // 2 left = merge_sort(arr[:mid]) right = merge_sort(arr[mid:]) return merge(left, right)
defmerge(left, right): result = [] i, j = 0, 0 while i < len(left) and j < len(right): if left[i] <= right[j]: result.append(left[i]) i += 1 else: result.append(right[j]) j += 1 result.extend(left[i:]) result.extend(right[j:]) return result
defmerge_sort_inplace(arr, low=0, high=None): if high isNone: high = len(arr) - 1 if low < high: mid = (low + high) // 2 merge_sort_inplace(arr, low, mid) merge_sort_inplace(arr, mid + 1, high) merge_inplace(arr, low, mid, high) return arr
defmerge_inplace(arr, low, mid, high): left = arr[low:mid + 1] right = arr[mid + 1:high + 1] i, j, k = 0, 0, low while i < len(left) and j < len(right): if left[i] <= right[j]: arr[k] = left[i] i += 1 else: arr[k] = right[j] j += 1 k += 1 while i < len(left): arr[k] = left[i] i += 1 k += 1 while j < len(right): arr[k] = right[j] j += 1 k += 1
defheap_sort(arr): n = len(arr) # 构建最大堆 for i inrange(n // 2 - 1, -1, -1): heapify(arr, n, i) # 逐个取出堆顶元素 for i inrange(n - 1, 0, -1): arr[0], arr[i] = arr[i], arr[0] heapify(arr, i, 0) return arr
defheapify(arr, n, i): largest = i left = 2 * i + 1 right = 2 * i + 2 if left < n and arr[left] > arr[largest]: largest = left if right < n and arr[right] > arr[largest]: largest = right if largest != i: arr[i], arr[largest] = arr[largest], arr[i] heapify(arr, n, largest)
使用 heapq 模块:
1 2 3 4 5 6
import heapq
defheap_sort_builtin(arr): heap = arr[:] heapq.heapify(heap) return [heapq.heappop(heap) for _ inrange(len(heap))]
defbucket_sort(arr, bucket_count=10): ifnot arr: return arr min_val = min(arr) max_val = max(arr) bucket_size = (max_val - min_val) / bucket_count + 1 buckets = [[] for _ inrange(bucket_count)] # 将元素分配到桶中 for num in arr: index = int((num - min_val) / bucket_size) buckets[index].append(num) # 对每个桶进行排序 for bucket in buckets: bucket.sort() # 可以使用其他排序算法 # 合并结果 result = [] for bucket in buckets: result.extend(bucket) return result
希尔排序(Shell Sort)
原理: 改进的插入排序,通过分组进行插入排序,逐步缩小间隔。
时间复杂度: 平均 O(n^1.3),最坏 O(n²) 空间复杂度: O(1) 稳定性: 不稳定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defshell_sort(arr): n = len(arr) gap = n // 2 while gap > 0: for i inrange(gap, n): temp = arr[i] j = i while j >= gap and arr[j - gap] > temp: arr[j] = arr[j - gap] j -= gap arr[j] = temp gap //= 2 return arr
defbubble_sort(arr): n = len(arr) for i inrange(n): for j inrange(0, n - i - 1): if arr[j] > arr[j + 1]: arr[j], arr[j + 1] = arr[j + 1], arr[j] return arr
6. O(n³) - 立方时间复杂度
1 2 3 4 5 6 7 8
defmatrix_multiplication(A, B): n = len(A) C = [[0] * n for _ inrange(n)] for i inrange(n): for j inrange(n): for k inrange(n): C[i][j] += A[i][k] * B[k][j] return C
7. O(2ⁿ) - 指数时间复杂度
1 2 3 4
deffibonacci_recursive(n): if n <= 1: return n return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)
8. O(n!) - 阶乘时间复杂度
1 2 3 4 5 6 7 8 9
defgenerate_permutations(arr): iflen(arr) <= 1: return [arr] result = [] for i inrange(len(arr)): rest = arr[:i] + arr[i+1:] for perm in generate_permutations(rest): result.append([arr[i]] + perm) return result
时间复杂度的计算方法
1. 单个循环
1 2 3 4
# O(n) for i inrange(n): # 常数时间操作 pass
2. 嵌套循环
1 2 3 4 5
# O(n²) for i inrange(n): for j inrange(n): # 常数时间操作 pass
3. 循环中的循环
1 2 3 4 5 6
# O(n²) for i inrange(n): for j inrange(i, n): # 常数时间操作 pass # 总次数:n + (n-1) + ... + 1 = n(n+1)/2 = O(n²)
4. 递归调用
1 2 3 4 5 6
# O(2ⁿ) deffibonacci(n): if n <= 1: return n return fibonacci(n - 1) + fibonacci(n - 2) # T(n) = T(n-1) + T(n-2) + O(1) ≈ O(2ⁿ)
defquick_sort(arr, low=0, high=None): if high isNone: high = len(arr) - 1 if low < high: pi = partition(arr, low, high) quick_sort(arr, low, pi - 1) quick_sort(arr, pi + 1, high) return arr
defis_valid(s): stack = [] mapping = {')': '(', ']': '[', '}': '{'} for char in s: if char in mapping: ifnot stack or stack.pop() != mapping[char]: returnFalse else: stack.append(char) returnlen(stack) == 0
5. 每日温度(下一个更大元素)
1 2 3 4 5 6 7 8 9 10 11
defdaily_temperatures(temperatures): result = [0] * len(temperatures) stack = [] # 存储索引 for i inrange(len(temperatures)): while stack and temperatures[stack[-1]] < temperatures[i]: index = stack.pop() result[index] = i - index stack.append(i) return result
defmax_sliding_window(nums, k): ifnot nums or k == 0: return [] deque_obj = deque() result = [] for i inrange(len(nums)): # 移除窗口外的元素 while deque_obj and deque_obj[0] < i - k + 1: deque_obj.popleft() # 移除小于当前元素的元素(保持单调递减) while deque_obj and nums[deque_obj[-1]] < nums[i]: deque_obj.pop() deque_obj.append(i) # 窗口形成后,记录最大值 if i >= k - 1: result.append(nums[deque_obj[0]]) return result