defmergeSort1(l, r): """ 归并排序递归版 T(n) = 2 * T(n/2) + O(n) 根据master公式,时间复杂度O(n * logn) 空间复杂度O(n) """ if l == r: # 递归终止条件:只剩一个元素 return m = (l + r) // 2# 计算中点 mergeSort1(l, m) # 递归排序左半部分 mergeSort1(m + 1, r) # 递归排序右半部分 merge(l, m, r) # 合并
defmerge(l, m, r): """ 合并两个有序区间 arr[l...m] 和 arr[m+1...r] 时间复杂度O(n),其中n = r - l + 1 """ i = l # help数组写指针 a = l # 左侧起始指针 b = m + 1# 右侧起始指针 # 双指针合并过程 while a <= m and b <= r: if arr[a] <= arr[b]: help_arr[i] = arr[a] a += 1 else: help_arr[i] = arr[b] b += 1 i += 1 # 处理剩余元素 while a <= m: help_arr[i] = arr[a] a += 1 i += 1 while b <= r: help_arr[i] = arr[b] b += 1 i += 1 # 写回原数组 for i inrange(l, r + 1): arr[i] = help_arr[i]
defmerge(l, m, r): """ 合并过程详解: 1. 双指针扫描:a指向左部分,b指向右部分 2. 比较合并:较小值写入help_arr,对应指针右移 3. 剩余处理:一边扫完后,另一边直接复制 4. 写回原数组:完成排序合并 """ i = l # help_arr写入位置 a = l # 左部分起点 b = m + 1# 右部分起点 # 两两比较,选择较小值 while a <= m and b <= r: if arr[a] <= arr[b]: help_arr[i] = arr[a] a += 1 else: help_arr[i] = arr[b] b += 1 i += 1 # 处理剩余元素(必有一边先结束) while a <= m: help_arr[i] = arr[a] a += 1 i += 1 while b <= r: help_arr[i] = arr[b] b += 1 i += 1 # 拷贝回原数组 for idx inrange(l, r + 1): arr[idx] = help_arr[idx]
defsmallSum(l, r): """ 返回arr[l...r]范围上小和的累加和,同时让arr[l..r]变有序 时间复杂度O(n * logn) """ if l == r: return0 m = (l + r) // 2 # 递归统计左右部分和跨区部分的小和 return smallSum(l, m) + smallSum(m + 1, r) + merge(l, m, r)
defmerge(l, m, r): """ 统计跨左右产生的小和,同时完成合并 """ ans = 0# 累计小和 i = l # 左侧指针 sum_left = 0# 累计左侧小于等于当前右侧元素的和 # 统计跨区贡献:对每个右侧元素,统计左侧贡献 for j inrange(m + 1, r + 1): # 左侧所有 <= arr[j] 的元素都对arr[j]有贡献 while i <= m and arr[i] <= arr[j]: sum_left += arr[i] # 累加左侧贡献 i += 1 ans += sum_left # arr[j]的左侧贡献总和 # 正常归并过程 i = l a = l b = m + 1 while a <= m and b <= r: if arr[a] <= arr[b]: help_arr[i] = arr[a] a += 1 else: help_arr[i] = arr[b] b += 1 i += 1 while a <= m: help_arr[i] = arr[a] a += 1 i += 1 while b <= r: help_arr[i] = arr[b] b += 1 i += 1 for idx inrange(l, r + 1): arr[idx] = help_arr[idx] return ans
defcounts(arr, l, r): """ 统计l...r范围上翻转对的数量,同时让l...r范围变有序 时间复杂度O(n * logn) """ if l == r: return0 m = (l + r) // 2 # 递归统计左右两边和跨区部分的翻转对数量 return counts(arr, l, m) + counts(arr, m + 1, r) + merge(arr, l, m, r)
defmerge(arr, l, m, r): """统计跨区翻转对并完成合并""" ans = 0# 翻转对计数 j = m + 1# 右边数组起点 # 统计跨区翻转对 for i inrange(l, m + 1): # 找到右侧第一个不满足 arr[i] > 2*arr[j] 的位置 while j <= r and arr[i] > 2 * arr[j]: j += 1 # 当前i能形成的翻转对数量 = j - (m+1) ans += j - m - 1 # 正常merge过程(与归并排序相同) i = l a = l b = m + 1 while a <= m and b <= r: if arr[a] <= arr[b]: help_arr[i] = arr[a] a += 1 else: help_arr[i] = arr[b] b += 1 i += 1 while a <= m: help_arr[i] = arr[a] a += 1 i += 1 while b <= r: help_arr[i] = arr[b] b += 1 i += 1 for idx inrange(l, r + 1): arr[idx] = help_arr[idx] return ans
classCode01_FillFunction: defsumOfSubMatrix(self, mat, n): """主方法,求n×n矩阵的最大子矩阵和""" returnself.maxSumSubmatrix(mat, n, n)
@staticmethod defmaxSumSubmatrix(mat, n, m): """求子矩阵的最大累加和""" max_sum = float('-inf') # 枚举上边界 for i inrange(n): arr = [0] * m # 辅助数组,每次重置 # 枚举下边界(从i到n-1) for j inrange(i, n): # 将第j行累加到辅助数组 for k inrange(m): arr[k] += mat[j][k] # 求当前辅助数组的最大子数组和 max_sum = max(max_sum, Code01_FillFunction.maxSumSubarray(arr, m)) return max_sum
@staticmethod defmaxSumSubarray(arr, m): """Kadane算法求最大子数组和""" max_sum = float('-inf') cur = 0 for i inrange(m): cur += arr[i] max_sum = max(max_sum, cur) cur = 0if cur < 0else cur # 负数时重置 return max_sum
# 静态空间分配,避免频繁内存分配 MAXN = 201 MAXM = 201 mat = [[0] * MAXM for _ inrange(MAXN)] arr = [0] * MAXM n = m = 0
defmain(): global n, m tokens = sys.stdin.read().split() idx = 0 output = [] while idx < len(tokens): n = int(tokens[idx]) idx += 1 m = int(tokens[idx]) idx += 1 # 读取矩阵数据到静态空间 for i inrange(n): for j inrange(m): mat[i][j] = int(tokens[idx]) idx += 1 # 计算结果并收集输出 output.append(str(maxSumSubmatrix())) # 批量输出所有结果 print('\n'.join(output))
defmaxSumSubmatrix(): """使用静态空间的子矩阵最大和算法""" max_sum = float('-inf') for i inrange(n): # 清空辅助数组(复用静态空间) for x inrange(m): arr[x] = 0 for j inrange(i, n): # 累加第j行到辅助数组 for k inrange(m): arr[k] += mat[j][k] max_sum = max(max_sum, maxSumSubarray()) return max_sum
defmaxSumSubarray(): """一维最大子数组和""" max_sum = float('-inf') cur = 0 for i inrange(m): cur += arr[i] max_sum = max(max_sum, cur) cur = 0if cur < 0else cur return max_sum
defreadInt(self): """快速读取整数""" num = 0 minus = False b = self.readByte() # 跳过非数字字符 while b != -1and (b < ord('0') or b > ord('9')) and b != ord('-'): b = self.readByte() if b == ord('-'): minus = True b = self.readByte() # 读取数字 while b != -1and (ord('0') <= b <= ord('9')): num = num * 10 + (b - ord('0')) b = self.readByte() return -num if minus else num
@staticmethod definOrder(head): """ 中序遍历非递归实现 核心思路:用一个栈模拟递归。每次不断沿左子树走到底,并将沿途所有节点入栈;遇到空节点就弹出栈顶节点,访问它,然后转向其右子树。如此反复,完整地实现“左-中-右”顺序。 测试链接LeetCode 94. 二叉树的中序遍历:https://leetcode.cn/problems/binary-tree-inorder-traversal/ """ if head isnotNone: stack = [] while stack or head isnotNone: if head isnotNone: # 当前节点不为空,压栈并继续向左 stack.append(head) head = head.left else: # 当前节点为空,说明左子树遍历完毕 head = stack.pop() # 弹出栈顶节点 print(head.val, end=" ") # 打印节点值(中序特点) head = head.right # 转向右子树 print()
原文标题:The central role of the propensity score in observational studies for causal effect 作者:PAUL R. ROSENBAUM, DONALD B. RUBIN 出处:Biometrilca (1083), 70, 1, pp. 41-55 doi号:点此查看全文 飞书链接:点此查看翻译版
deftwo_pointer_pattern(head): """ 双指针模式:快慢指针、左右指针等 常用于链表中点查找、环检测、倒数第k个节点等 """ slow = fast = head # 快慢指针初始化 while fast and fast.next: slow = slow.next# 慢指针每次移动1步 fast = fast.next.next# 快指针每次移动2步 return slow # 返回中点或其他目标位置
defrecursive_pattern(head): """ 递归模式:将复杂问题分解为子问题 适用于链表反转、删除节点、合并等操作 """ # 基础情况 if head isNoneor head.nextisNone: return head # 递归处理子问题 result = recursive_pattern(head.next) # 处理当前层 # ... return result
deflinear_search_exist(arr, target): """ 线性搜索验证方法 用于对数器验证二分搜索的正确性 """ for element in arr: # 遍历数组每个元素 if element == target: # 找到目标值 returnTrue returnFalse# 未找到目标值
defbinary_search_left_bound(arr, target): """ 在有序数组中查找 >= target 的最左位置 参数: arr - 有序数组, target - 目标值 返回: 满足条件的最左索引,不存在返回-1 """ if arr isNoneorlen(arr) == 0: return -1 left, right = 0, len(arr) - 1 ans = -1# 记录答案,初始化为-1表示未找到 while left <= right: mid = left + (right - left) // 2 if arr[mid] >= target: # 当前元素满足条件 ans = mid # 更新答案 right = mid - 1# 继续在左半部分寻找更左的位置 else: # 当前元素小于target left = mid + 1# 在右半部分继续搜索 return ans
deflinear_search_left_bound(arr, target): """线性搜索验证:查找>=target的最左位置""" for i inrange(len(arr)): # 从左到右遍历 if arr[i] >= target: # 找到第一个满足条件的位置 return i return -1# 未找到