簡體   English   中英

查找相等和的contiguos子數組

[英]Finding contiguos subarray of equal sum

Given array : 8 3 5 2 10 6 7 9 5 2
So the o/p will be Yes.   

如:{8,3,5} {10,6} {9,5,2}它們都具有相同的總和,即16。

But for this array : 1 4 9 6 2 12
      o/p will be No.

如:沒有連續的幻燈片具有相同的總和值

我本來打算使用SubSetSum算法/ Kadane最大子數組算法,但后來我最終遇到了,因為所有算法都需要預先定義的目標和。 但是這里我們不知道目標金額

如果給出了所需的總和,並且所有子數組都應該是連續的,那么可以很容易地在O(n)

運行在陣列的環和保持片(的邊界leftright索引)和currentSum

從第一個元素開始為0。邊界將為[0,0](為簡單起見,我們將其包括在內)。 然后,您具有三個條件。

  1. 如果總和小於期望值,則在總和中添加right元素並提前right索引
  2. 如果總和大於期望值,請從總和中刪除左元素並前進左索引
  3. 如果總和等於給定,則打印切片。 為了避免在下一次迭代中出現此切片,請提前向左索引並調整和。

翻譯成代碼

    public static void main(String[] args) {
        int givenSum = 16;
        int[] a = new int[] {8, 3, 5, 2, 10, 6, 7, 9, 5, 2};

        // boundaries of slice
        int left = 0; // defines position of slice
        int right = 0; // exclusive
        int currentSum = 0;

        while (right < a.length) {

            if (currentSum < givenSum) { // sum is not enough, add from the right
                currentSum += a[right];
                right++;
            }

            if (currentSum > givenSum) { // sum exceeds given, remove from the left
                currentSum -= a[left];
                left++;
            }

            if (currentSum == givenSum) { // boundaries of given sum found, print it
                System.out.println(Arrays.toString(Arrays.copyOfRange(a, left, right)));
                // remove the left element, so we can process next sums
                currentSum -= a[left];
                left++;
            }
        }

    }

對於您的情況,它會打印4片,總和為16

[8, 3, 5]
[10, 6]
[7, 9]
[9, 5, 2]

編輯:

正如OP所闡明的,沒有給定的總和,目標是檢查是否存在至少兩個不同的連續子數組,它們產生相等的總和。

最直接的算法是生成所有可能的總和,並檢查是否存在重復項

int[] a = new int[] {1, 4, 9, 6, 2, 12};

HashSet<Integer> sums = new HashSet<>();
int numOfSums = 0;

for (int left = 0; left < a.length - 1; left++) {
    for (int right = left; right < a.length; right++) {
        // sum from left to right
        int sum = 0;
        for (int k = left; k <= right; k++) {
            sum += a[k];
        }
        numOfSums++;
        sums.add(sum);
    }
}
System.out.println(sums.size() == numOfSums);

這的復雜度是O(n^3) ,不是一個好值,但是可行。

提示:可以探索一種技巧將其提升為O(n^2) ,您無需為每對切片計算總和!

您可以通過以下方式進行

  1. 您的總和= 48
  2. 現在,每個子集的總和等於48的因數。因數越小,您可以將其細分為更多的子集
  3. 對於總和的所有因子,請檢查該因子的答案是否可行。 只需遍歷數組即可在O(n)中完成。
  4. 時間復雜度為O(n * factor(sum))

使用動態編程查找數組的所有子和,然后找到具有相同和的子數組。 復雜度應為O(n2)。

    void subsum(int n, int* arr, int** sum) {
         for (int i = 0; i < n; ++i) {
              sum[i][i] = arr[i];
         }
         for (int l = 2; l <= n; ++l) {
              for (int i = 0; i < n - l + 1; ++i) {
                   sum[i][i + l - 1] = sum[i][i + l - 2] + arr[i + l -1];
              }
         }
     }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM