给定n个元素的数组(例如[1,2])和数字'k'(例如6),找到所有可能的方法来产生sum = k
对于给定的示例,答案是4,因为
1 1 1 1 1 1
1 1 1 1 2
1 1 2 2
2 2 2
我能想到的算法是蛮力,我们模拟所有可能的场景,并在从给定状态停止时我们无法达到结果。
arr[] = [1,2]
k = 6
globalCount =0;
function findSum(arr,k)
{
if(k ==0)
globalCount++
return
else if(k<0)
return
for each i in arr{
arr.erase(i)
tmp = k
findSum(arr,tmp)
while(k>=0){
findSum(arr,tmp -= i)
}
}
我不确定我的解决方案是否最有效。请评论/更正或显示更好解决方案的指示。
编辑:如果有人能给我代码的运行时复杂性和他们的soln代码,真的很感激。 :) 我认为我的代码复杂度是Big-O(n ^ w)w = k / avg(arr [0] .. arr [n-1])答案 0 :(得分:5)
如果你愿意原谅那些花哨的linq技巧,你会发现这个C#解决方案很有用。幸运的是,linq读起来有点像英语。我们的想法是建立解决方案,因为k
从0开始并递增,直到达到正确的值。 k
的每个值都基于先前的解决方案。但是你需要注意的一件事是确保你找到的新“方式”不是其他人的重新排序。我解决了这个问题,只计算它们是有效的,如果它们被排序的话。 (这只是一个比较)
void Main() {
foreach (int[] way in GetSumWays(new[] {1, 2}, 6)) {
Console.WriteLine (string.Join(" ", way));
}
}
int[][] GetSumWays(int[] array, int k) {
int[][][] ways = new int[k + 1][][];
ways[0] = new[] { new int[0] };
for (int i = 1; i <= k; i++) {
ways[i] = (
from val in array
where i - val >= 0
from subway in ways[i - val]
where subway.Length == 0 || subway[0] >= val
select Enumerable.Repeat(val, 1)
.Concat(subway)
.ToArray()
).ToArray();
}
return ways[k];
}
输出:
1 1 1 1 1 1
1 1 1 1 2
1 1 2 2
2 2 2
它使用动态编程方法,应该比天真的递归方法更快。我认为。我知道它足够快,可以计算在几毫秒内打破一美元的方法。 (242)
答案 1 :(得分:2)
这是分区问题的一个有趣子集。如果允许所有整数,实际上有一个封闭形式的解决方案(参见here和here)。
对“限制分区功能”进行一些谷歌搜索给了我一些线索。 This paper对此问题的几个解决方案进行了非常严格的数学讨论,this one也是如此。
不幸的是,我太懒了,不能编码。他们是非常强烈的解决方案。
答案 2 :(得分:0)
static void populateSubsetSum(int[]a,int K,int runSum,int idx,ArrayList<ArrayList<Integer>> ans,ArrayList<Integer> al){
if(idx>=a.length || runSum>K)
return;
if(runSum==K){
ans.add(new ArrayList<>(al));
return;
}
ArrayList<Integer> temp=new ArrayList<>(al);
temp.add(a[idx]);
populateSubsetSum(a,K,runSum+a[idx],idx,ans,temp);//when repitions of elements are allowed
populateSubsetSum(a,K,runSum,idx+1,ans,al);
}
将此函数称为:
populateSubsetSum(a,K,0,0,ans,new ArrayList<>());//array,sum,initial_sum,global 2d list,temp list