n颗糖果分配给3个孩子的合规分配方式计数及Python代码优化与列表推导式修正求助
优化糖果分配问题的Python代码与列表推导式修复
嘿,我来帮你搞定这个问题!作为编程新手,你能自己写出代码已经很棒了,咱们一步步来优化它,顺便把列表推导式的问题解决掉。
先理清楚问题本质
首先,咱们先明确需求:把n颗糖果分给3个孩子,要求每个孩子至少1颗,且至少有一个孩子的糖果数比另外两个都多。其实换个角度想,这个需求等价于:所有满足“每个孩子至少1颗”的分配方式,减去“三个孩子糖果数完全相等”的情况(只有当n是3的倍数时才存在这1种情况)。
比如n=6时,总共有10种“每个孩子至少1颗”的分配方式,去掉(2,2,2)这1种,剩下的9种就是有效解,和你举的例子一致。
原代码的问题分析
你的原代码有几个可以优化的点:
- 三重循环效率太低:遍历所有i、j、k从1到n,大部分组合都不满足i+j+k=n,完全是浪费计算资源。
- 排列去重逻辑冗余:你用
itertools.permutations生成排列再去重,最后还把这些排列组存到列表里再展开,逻辑绕了弯路,而且容易出错。 - 条件判断可以简化:
(i!=j or j!=k)其实和not (i==j==k)是一个意思,但原代码的去重逻辑导致重复添加或遗漏。
优化后的代码(含正确的列表推导式)
我们可以直接用列表推导式生成所有符合要求的有序分配方式(因为分给不同的孩子,(1,4,1)和(4,1,1)是不同的有效方式):
n = int(input()) # 方式1:直接生成所有有效有序分配(高效简洁) valid_distributions = [ (i, j, n - i - j) for i in range(1, n - 1) for j in range(1, n - i) if not (i == j == n - i - j) ] # 打印结果 print("所有有效分配方式:") for dist in valid_distributions: print(dist) print(f"总共有 {len(valid_distributions)} 种方式")
代码解释:
- 我们只遍历满足
i >=1、j >=1且i+j <n的组合,因为k = n-i-j必须至少为1,这样直接过滤掉了绝大多数无效组合。 if not (i == j == n - i - j)用来排除三个孩子糖果数完全相等的情况,正好满足需求。
另一种优化思路:先找基础模式再生成排列
如果想先找出不重复的“分配模式”(比如把(1,1,4)、(1,4,1)、(4,1,1)看作同一个基础模式),再生成所有排列,这种方式在n较大时效率更高:
import itertools n = int(input()) # 第一步:生成无重复的基础分配模式(不考虑孩子顺序) base_patterns = set() for i in range(1, n//3 + 1): for j in range(i, (n - i)//2 + 1): k = n - i - j if k >= j and not (i == j == k): base_patterns.add((i, j, k)) # 第二步:生成每个基础模式的所有唯一排列 valid_distributions = [] for pattern in base_patterns: perms = set(itertools.permutations(pattern)) valid_distributions.extend(perms) # 可选:给结果排序,方便查看 valid_distributions = sorted(valid_distributions) # 打印结果 print("所有有效分配方式:") for dist in valid_distributions: print(dist) print(f"总共有 {len(valid_distributions)} 种方式")
为什么你的列表推导式出错?
你写的列表推导式逻辑混乱,主要问题是:
- 把条件判断和元素生成混在了一起,语法错误。
- 在列表推导式里引用
arr(还没生成的列表),这在Python里是不允许的,因为arr在推导式执行时还不存在。 - 多余的排列去重操作,导致逻辑绕远路。
咱们上面的列表推导式已经完美解决了这个问题,直接生成所有有效分配,不需要额外的去重操作。
内容的提问来源于stack exchange,提问作者Shubham Nanche




