给定一个非负整数数组和一个数字。您需要打印总和等于给定整数的子数组的所有开始和结束索引。
例如 :
Input-int[] arr = {2, 3, 6, 4, 9, 0, 11};
int num = 9
Output-
starting index : 1, Ending index : 2
starting index : 5, Ending index : 5
starting index : 5, Ending index : 6
Explanation :
[3, 6] [9],
[9,0] These all are the subarrays with their sum equal to 9.
解决这个问题的基本蛮力方法是生成给定数组的所有子数组,然后遍历生成的子数组并计算总和,如果这个总和等于给定的总和,则打印这个子数组,因为它是我们解决方案的一部分。
现在我们知道,一个有 n 个元素的数组有n*(n+1)/2 个子数组。
如何?
考虑一个数组,
int[] arr = {a1, a2, a3, a4…, an};
Subarrays starting with 0th index,
a1
a1, a2
a1, a2, a3
a1, a2, a3, a4
.
.
.
a1, a2, a3, a4…, an
Subarrays starting with 1st index,
a2
a2, a3
a2, a3, a4
.
.
.
a2, a3, a4…, an
subarrays starting with 2nd index,
a3
a3, a4
.
.
.
a3, a4…, an
Subarrays starting with last i.e. 3rd index,
a4
.
.
.
a4…, an
现在,
总子数组= 从第 0 个 idx开始的子数组+从第 1 个 idx 开始的子数组+
从第 2 个 idx + 开始的子数组。. . + 以第 n 个 idx 开头的子数组
Sn = n + (n-1) + (n-2) + (n-3) + ... + 1
Sn = n(n+1)/2
在那里,生成所有子数组并计算答案将花费我们最坏的时间复杂度,O(n(n+1)/2)其顺序为O(n^2)。
package Arrays;
import java.util.Scanner;
public class targetsumSubarr {
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
int[] arr = new int[scn.nextInt()];
int target = scn.nextInt();
for (int i = 0; i < arr.length; i++) {
arr[i] = scn.nextInt();
}
solve(arr, target);
}
public static void solve(int[] arr, int target)
{
for(int start = 0; start < arr.length; start++)
{
// initialize the sum of the current subarray to 0.
int currSum = 0;
for(int end = start; end < arr.length; end++)
{
// add every element of the current subarray
// to the current running sum.
currSum += arr[end];
// print the starting and ending indices once we get
// subarray with given sum
if(currSum == target)
{
System.out.println("starting index : " +
start + ", " + "Ending index : " + end);
}
}
}
}
}
有效的方法:
我们可以在线性时间内解决这个问题,即O(n)最坏的时间复杂度。
我们可以维护两个指针,一个基本上代表一个子数组的指针,start并且end我们必须取一个变量来存储current sum从开始指针到结束指针的子数组的。
我们end在添加元素的同时不断增加指针,current sum直到我们到达当前运行总和大于所需目标总和的点,这基本上意味着我们计算出的总和不是正确答案的当前子数组。
所以现在我们通过移动start指针来改变我们的子数组,即缩短子数组,从而缩短当前总和,希望我们实现当前总和等于所需的目标总和。
在每一点我们检查我们当前的总和是否等于目标总和,如果是这种情况我们打印我们的指针。
所以基本上,我们通过增加改变子数组start和end指针和改变取决于它的价值相比,目标总电流总和。
package org.arpit.java2blog;
import java.util.Scanner;
public class TargetsumSubarr {
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
int[] arr = new int[scn.nextInt()];
int target = scn.nextInt();
for (int i = 0; i < arr.length; i++) {
arr[i] = scn.nextInt();
}
System.out.print("arr[]: {");
for (int i = 0; i < arr.length; i++) {
System.out.print(" "+arr[i]);
}
System.out.println(" }");
solveEfficient(arr, target);
}
public static void solveEfficient(int[] arr, int target) {
int start = 0, end = 0;
int currSum = 0;
while (start < arr.length && end <= arr.length) {
if (currSum == target) {
/* as the currSum is equal to target sum, print the
* result with end as end-1.
* because when we added the element at end we
* increased the pointer there only,
* so now we need to subtract 1 because the
* subarray constituting that sum has
* its last pointer one index where end is currently at.
*/
System.out.println("starting index : " + start + ", " +
"Ending index : " + (int) (end - 1));
if (end <= arr.length - 1) {
currSum += arr[end];
}
end++;
}
else {
/* if the currSum becomes more than required,
* we keep on subtracting the start element
* until it is less than or equal to
required target sum. */
if (currSum > target) {
currSum -= arr[start];
start++;
} else {
/* we add the last element to our
* currSum until our
* sum becomes greater than or
* equal to target sum.
*/
if (end <= arr.length - 1) {
currSum += arr[end];
}
end++;
}
}
}
}
}
当你运行上面的程序时,你会得到以下输出:
7
9
2 3 6 4 9 0 11
arr[]: { 2 3 6 4 9 0 11 }
starting index : 1, Ending index : 2
starting index : 4, Ending index : 4
starting index : 4, Ending index : 5
本文向大家介绍编写Golang程序以在数组(O(n))中查找具有给定总和的对,包括了编写Golang程序以在数组(O(n))中查找具有给定总和的对的使用技巧和注意事项,需要的朋友参考一下 例子 输入数组= [1、3、5、7、8、9],总和= 11 =>(3,8) 解决这个问题的方法 步骤1: 定义一个接受数组和sum的方法。 步骤2: 定义一个映射变量,输入map [int] int。 步骤3:将
我在一次采访中被问到以下问题。虽然我用n元树回答了这个问题,但有人告诉我这还不够好。所以,我很好奇,什么是它的最佳解决方案。 输入:整数数组:[2,3,7]和总和:10 输出:加起来等于和的所有数组元素组合(例如2、2、3、3、7等) 谢了小泰
给定一个整数数组和一个整数m,我如何找到所有包含m个奇整数的子数组?如果我的问题不充分,下面是对整个问题的更长描述。这个问题有比n^2更快的解决方案吗?下面的解决方案似乎是n^2,我不确定如何进一步优化它。 https://github.com/cem3394/hr-haskell/blob/master/beautifulsubarrays.hs
本文向大家介绍编写Golang程序以在数组中找到具有给定总和的对(O(nlogn)),包括了编写Golang程序以在数组中找到具有给定总和的对(O(nlogn))的使用技巧和注意事项,需要的朋友参考一下 例子 输入数组= [1、3、5、7、8、9],总和= 11 =>(3,8) 解决这个问题的方法 步骤1: 定义一个接受数组和sum的方法。 步骤2: 对给定的数组进行排序,声明low:= 0和hi
我在一次采访中被问到这个问题。给定一个整数数组(具有正值和负值),我们需要找到具有相等总和的不相交子数组的最大数量。 例子: 输入:[1,2,3]输出:2{因为我们最多有2个子数组,总和=3,即[1,2],[3]} 输入: [2 2 2 -2] 输出 : 2 {两个子数组,每个子数组的总和 = 2,即 [2],[2, 2, -2]} 我的方法 我想到的第一种方法是找到前缀和数组,然后以每个元素(前
给定一个数组,计算具有给定总和的子数组的数量,使得索引按升序排列(它们不需要连续,但数组元素的索引应该按升序排列。) 例如,-Array-{1 2 3 4 5},Sum-5 Then{1,4}也是一个有效的子数组,因为索引是按升序(1 注意——这个问题看起来非常类似于子数组的计数问题,但是当索引以升序排列时就变得更加复杂了,因为那时会有更多的值。我请求有人请分享同样的伪代码,如果不可能,分享逻辑。