我可以搜索带有和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}。
答案 0 :(得分:0)
O(N^2)
解决方案对于每个索引i
,预先计算从0
到i
的子阵列的总和。然后,要查找任何子阵列(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>
并使用给定的总和存储所有索引。