计算将数组划分为三个具有相等和的连续部分的方式的数量

问题描述 投票:-1回答:3

我有一个数组,我必须计算数种将其分成3个连续部分的方式,以使它们的总和相等。如何修改分区问题呢?例如-令A为包含{{1,2,3,0,3}的数组答案-2因为它可以分为{{1,2},{3},{0,3}}{{1,2},{3,0},{3}}相等的和。

arrays partition
3个回答
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数组。我相信这是大多数库中最常见的行为。

您对输入的了解越多,可以添加更多捷径来使其更高效。例如;如果您知道该数组仅包含正数,那么当您的总和大于目标值时,您可以停止测试分区,因为无论您添加什么正数,它都永远不会将总和降低到目标值。


0
投票

在提出的问题中,我们需要在一个总和相同的数组中找到三个连续的部分。我将提及这些步骤以及可为您解决问题的代码段。

  1. [通过执行线性扫描O(n)并计算sum / 3来获得数组的和。
  2. 从头开始扫描给定的数组。在每个索引处,我们需要存储获得等于(sum / 3)的总和的方式数,即,如果end [i]为3,则数组中有3个子集,从索引i到n(数组范围)其中sum为sum / 3。
  3. 第三也是最后一步是从头开始扫描,并找到sum为sum / 3的索引。找到索引后,将其添加到解决方案变量(初始为零),结束[i + 2]。

这里我们要做的是,从头开始遍历数组直到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]++;
    }
}

一旦有了end数组,我们就进行正向循环并获得最终解决方案

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];
    }
}

solution存储最终答案,即将数组拆分为三个具有相等总和的连续部分的方式的数目。


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
  */
© www.soinside.com 2019 - 2024. All rights reserved.