返回信息流请帮忙给点思路:
一个数字例如100,分解成为固定个数的加数,例如20个数字,每个数字必须小于等于10,求所有的分解方式
这是一条镜像帖。来源:北邮人论坛 / java / #58324同步于 2017/12/13
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
一个数的分解为固定长度加数的所有分解方法
kyle
2017/12/13镜像同步9 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
大致的想法吧,复杂度略高:
假设都是整数:
1. 总和为 sum,要分成 n 份,每份不得多于 m,则当 sum/n < m 时,可以产生第一份。
2. 假设从 i = 1; 开始分,则 r[0] = i; sum -= i; n -= 1;
3. 继续产生下一份,但是要检测 sum/n < m,成立才能继续分当前的 i ,否则 i 就要增加使得 sum/n < m 成立,因为一旦剩下的均分之后大于临界值,则必有一个会超出该临界值,直到最后 sum/n < m 不再成立或已经达到 i == m 。
4. 一次遍历完后使前一个容器中的值 +1,如果不超过 m,又可以继续往后重复3,如此回溯直至 r[0] == m,到达最后一次遍历。
算是穷举,时间复杂度略大,还有一种就是看成倒水操作,n 个杯子,每个装水最多 m ,排列组合装下 sum 的水。
等个更好的算法。
LeetCode39题变形题,只是需要list.size=20
【 在 cm11524022 (菜小鸡) 的大作中提到: 】
: 166627种?
nums=[1,2,3,4,5,6,7,8,9,10],target=100
【 在 cm11524022 (菜小鸡) 的大作中提到: 】
: LeetCode39题变形题,只是需要list.size=20
````java
public class CombinationSum {
public List<List<Integer>> combinationSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<Integer>(), nums, target, 0);
System.out.println(list.size());
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tmp, int[] nums, int target, int start) {
if (target < 0) {
return;
} else if (target == 0) {
if (tmp.size() == 20) {
list.add(new ArrayList<>(tmp));
} else {
return;
}
} else {
for (int i = start; i < nums.length; i++) {
tmp.add(nums[i]);
backtrack(list, tmp, nums, target - nums[i], i);
tmp.remove(tmp.size() - 1);
}
}
}
public static void main(String[] args) {
CombinationSum c = new CombinationSum();
c.combinationSum(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 100);
}
}
```
答案为 166627 种。 最近刚刷到这个题
求方案数的话类似用动态规划的方法。
如果求每个方案的话那就只能搜索了。
类似于二楼的方法可以有一个剪枝,分解成k个数的话,数字上下界应该是k-k*m.
可能要考虑一下重复的问题,于是就要求下一个分解的数必须小于等于或者大于等于上一个分解得到的数,于是可以更好地控制分解的上下界