对于负数和正数,小于O(n2)的子阵列总和等于k

时间:2017-09-06 13:43:27

标签: java arrays algorithm

我可以搜索带有和eqaul到k的正数的子数组,但是下面的代码对数组中的负数没有成功。是否存在一种算法,用于查找数组中负数和正数的给定和的子数组?

public static void subarraySum(int[] arr, int sum) {

    int start=0;
    int currSum=arr[0];

    for(int i = 1;i<=arr.length;i++) {
        while(currSum>sum ) {
            currSum-=arr[start];
            start++;
        }
        if(currSum==sum) {
            System.out.println(start + " " + (i-1) + " index");
            start=i;
            currSum=0;
        }
        if(i<arr.length) {
            currSum +=arr[i];
        }

    }
}

例如,{10,2,-2,-20,10},在此数组中查找带和-10的子数组。 在这种情况下,子阵列将是{-20,10}。

1 个答案:

答案 0 :(得分:0)

O(N^2)解决方案

对于每个索引i,预先计算从0i的子阵列的总和。然后,要查找任何子阵列(i, j)的总和,您只需计算sum[j] - sum[i] + arr[i]

  public static void subArraySum(int[] arr, int target) {
    if (arr.length == 0) return;

    int n = arr.length;
    int[] sum = new int[n];
    sum[0] = arr[0];
    for (int i = 1; i < n; ++i) {
        sum[i] = sum[i - 1] + arr[i];
    }

    for (int i = 0; i < n; ++i)
      for (int j = i; j < n; ++j)
        if (sum[j] - sum[i] + arr[i] == target) {
            System.out.println(i + " " + j);
        }
  }

更快的解决方案

如果您将总和存储在地图中,然后查询此地图以获得所需的总和,则可以更快地找到子阵列。

 public static void subArraySum(int[] arr, int target) {
  if (arr.length == 0) return;

  int n = arr.length;
  int[] sum = new int[n];
  sum[0] = arr[0];
  for (int i = 1; i < n; ++i) {
      sum[i] = sum[i - 1] + arr[i];
  }

  Map<Integer, Integer> map = new TreeMap<>();
  for (int i = 0; i < n; ++i) {
      if (sum[i] == target) {
          System.out.println(0 + " " + i);
      }

      int requiredSum = sum[i] - target;
      if (map.containsKey(requiredSum)) {
          int startIndex = map.get(requiredSum) + 1;
          System.out.println(startIndex + " " + i);
      }
      map.put(sum[i], i);
  }
}

此解决方案为O(N*logN),但如果您假设HashMap操作复杂度不变,则可以使用HashMap而不是TreeMap(O(N))来加快速度。

请注意,此解决方案不会打印所有可能的对。如果您需要找到具有给定总和的所有子数组,则需要使用Map<Integer, Array<Integer>>而不是Map<Integer, Integer>并使用给定的总和存储所有索引。