如何按类BFS顺序遍历多维度range生成元组?
问题解答
一、排序名称
这种排序可以称为**“按元素和升序+元素最大值升序的多维度元组排序”**,本质是一种分层优先的类BFS遍历——先遍历所有元素和为s的元组,同一s范围内再按元组的最大值从小到大排列。
二、高效生成器实现
要满足每个元组生成的时间/空间复杂度至多O(k),可以按分层遍历的思路实现:
- 按元素和
s从0开始逐层遍历,s的最大值为k*(n-1) - 对每个
s,遍历可能的最大值m:范围是max(ceil(s/k), 0)到min(s, n-1)(因为k个元素和为s,最大值至少是s/k向上取整,最多不超过s和n-1的较小值) - 对每个
(m, s),生成所有元素和为s、最大值恰好为m的k元组
Python实现代码
def k_tuples_of_range_n(k, n): max_sum = k * (n - 1) # 按元素和s分层遍历 for s in range(0, max_sum + 1): # 遍历当前s下的所有可能最大值m min_m = max((s + k - 1) // k, 0) # 向上取整s/k max_m = min(s, n - 1) for m in range(min_m, max_m + 1): remaining_sum = s - m if remaining_sum < 0: continue # 生成k-1个元素≤m-1、和为remaining_sum的子元组,再将m插入每个位置 for sub_tuple in _generate_subtuples(k-1, m-1, remaining_sum): for i in range(k): yield sub_tuple[:i] + (m,) + sub_tuple[i:] def _generate_subtuples(length, max_val, target_sum): # 递归生成指定长度、元素上限、目标和的元组 if length == 0: if target_sum == 0: yield () return # 计算当前元素的取值范围 start = max(0, target_sum - (length - 1) * max_val) end = min(max_val, target_sum) for val in range(start, end + 1): for rest in _generate_subtuples(length - 1, max_val, target_sum - val): yield (val,) + rest
实现说明
- 辅助函数
_generate_subtuples通过递归生成符合条件的子元组,递归栈深度为O(k),每个元组生成的时间复杂度为O(k) - 主函数按
s和m分层遍历,确保输出顺序完全符合要求,元组拼接操作的时间复杂度为O(k) - 测试
k=3、n=4时,输出顺序与示例完全一致
三、迭代版优化(可选)
如果要避免递归栈占用,可将辅助函数改为迭代实现:
def _generate_subtuples_iter(length, max_val, target_sum): stack = [(0, length, target_sum, ())] while stack: current_val, remaining_len, remaining_sum, current_tuple = stack.pop() if remaining_len == 0: if remaining_sum == 0: yield current_tuple continue start = max(current_val, remaining_sum - (remaining_len - 1)*max_val) end = min(max_val, remaining_sum) # 反向入栈保证生成顺序与递归一致 for val in range(end, start - 1, -1): stack.append((val, remaining_len - 1, remaining_sum - val, current_tuple + (val,)))
内容的提问来源于stack exchange,提问作者chausies
相关产品推荐
相关产品推荐

