我有一个数组,我必须计算多种方法将它分成3个连续的部分,使它们的总和相等。如何修改分区问题呢?
例如 -
让 A 成为包含 {1,2,3,0,3} 的数组
回答 - 2
因为它可以分为 {{1,2},{3},{0,3}} 和 {{1,2},{3,0},{3} } 有相同的金额。
答案 0 :(得分:0)
如果我理解正确,那么您就是在限制问题,以至于您无法重新排列数组中值的顺序。假设问题集合理,您可以轻松地遍历并测试每个可能的变化。这将是递归的,但不需要动态编程。我面前没有IDE,但我相信代码看起来像这样(适应所选语言):
public int countWays(Array array) {
int count = 0;
int sum = 0;
for (int index = 0; index < array.length(); ++index) {
// how much would each partition sum to if we partitioned here?
sum += array.get(index);
// how many ways could the rest of the array be split to match that sum?
count += recursiveCount(sum, array.subArray(index + 1, array.length());
}
return count;
}
public int recursiveCount(int partitionSum, Array remaining) {
// base case
if (remaining.length() == 0) {
return 1;
}
int count = 0;
int sum = 0;
for (int index = 0; index < remaining.length(); ++index) {
// how much would this partion sum to if we partitioned here?
sum += remaining.get(index);
// did we hit the mark?
if (sum == partitionSum) {
// make a partion here and see if we can finish the rest of the array
count += recursiveCount(paritionSum, remaining.subArray(index + 1, remaining.length());
}
}
return count;
}
*注意:这假设一个subArray函数,它从第一个索引包含到第二个索引,专门创建一个NEW数组。我相信这是大多数图书馆中最常见的行为。
您对输入的了解越多,您可以添加更多的快捷方式,以提高效率。例如;如果您知道数组只包含正数,那么当您的总和大于目标值时,您可以停止测试分区,因为无论您添加什么正数,它都不会将总和返回到目标值。
答案 1 :(得分:0)
在提出的问题中,我们需要在数组中找到三个连续的部分,它们的总和是相同的。我将提及步骤以及将为您解决问题的代码片段。
我们正在做的事情是,从start开始遍历数组,直到len(array)-3。在找到总和,sum / 3,比如说索引i,我们有上半部分。
现在,不关心下半部分并将解决方案变量(启动为零)添加到等于end [i + 2]的值。 end [i + 2]告诉我们从i + 2开始到结束的总方式,得到的数量等于第三部分的sum / 3.
在这里,我们所做的是处理第一和第三部分,我们也处理了第二部分,它将默认等于sum / 3。我们的解决方案变量将是问题的最终答案。
以下是代码片段,以便更好地理解上述算法:: -
在这里,我们正在进行向后扫描,以存储从每个索引的末尾获得sum / 3的方式的数量。
long long int *end = (long long int *)calloc(numbers, sizeof(long long int);
long long int temp = array[numbers-1];
if(temp==sum/3){
end[numbers-1] = 1;
}
for(i=numbers-2;i>=0;i--){
end[i] = end[i+1];
temp += array[i];
if(temp==sum/3){
end[i]++;
}
}
一旦我们有了结束数组,我们就会进行前向循环并得到我们的最终解决方案
long long int solution = 0;
temp = 0;
for(i=0;i<numbers-2;i++){
temp+= array[i];
if(temp==sum/3){
solution+=end[i+2];
}
}
解决方案存储最终答案,即将数组拆分为三个具有相等总和的连续部分的方式。
答案 2 :(得分:0)
这是一个经过纠正的工作解决方案,其中有两个基于@Mattew Pape答案的示例。但这是尝试所有可能分区的蛮力方法。可以进一步优化。此方法的复杂度为O(N!)。
public class partitonArray {
static int total = 0;
public static int countWays(int [] arr) {
int sum = 0;
for (int index = 0; index < arr.length; ++index) {
sum += arr[index];
List<List<Integer>> lst = new ArrayList();
List<Integer> l1 = new ArrayList();
for(int j=0;j<=index;j++)
l1.add(arr[j]);
lst.add(l1);
recursiveCount(sum, Arrays.copyOfRange(arr, index + 1, arr.length), lst);
}
return total;
}
public static void recursiveCount(int partitionSum, int [] remaining, List<List<Integer>> lst) {
// base case
if (remaining.length == 0 && lst.size() > 1) {
System.out.println("Result here = "+lst.toString());
total++;
}
int sum = 0;
List<Integer> l1 = new ArrayList();
for (int index = 0; index < remaining.length; ++index) {
sum += remaining[index];
l1.add(remaining[index]);
// did we hit the mark?
if (sum == partitionSum) {
// make a partion here and see if we can finish the rest of the array
lst.add(l1);
recursiveCount(partitionSum, Arrays.copyOfRange(remaining, index + 1, remaining.length), lst);
lst.remove(l1);
}
}
}
public static void main(String [] args) {
//int [] arr ={ 2, 4, 6,7, 7, 6, 3, 3, 3, 4, 3, 4,5, 4, 4, 3, 3, 1,4};
int [] arr = {1, 2, 3, 0, 3};
System.out.println(countWays(arr));
}
}
**Output**:
Result here = [[1, 2], [3], [0, 3]]
Result here = [[1, 2], [3, 0], [3]]
2
/*
Result here `enter code here`= [[2, 4, 6, 7], [7, 6, 3, 3], [3, 4, 3, 4, 5], [4, 4, 3, 3, 1, 4]]
Result here = [[2, 4, 6, 7, 7, 6, 3, 3], [3, 4, 3, 4, 5, 4, 4, 3, 3, 1, 4]]
2
*/
答案 3 :(得分:0)
解决方法如下:
例如: {1、2、3、0、3} 。让我们执行上述步骤。
我的解决方案: https://github.com/setu1421/programming-revamp/blob/master/InterviewBit/Arrays/Partitions.cpp