当前位置: 首页 > 面试题库 >

在数组中查找具有给定总和的子数组。

陶鸿畴
2023-03-14
问题内容

给定一个非负整数数组和一个数字。您需要打印总和等于给定整数的子数组的所有开始和结束索引。
例如 :

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 注意——这个问题看起来非常类似于子数组的计数问题,但是当索引以升序排列时就变得更加复杂了,因为那时会有更多的值。我请求有人请分享同样的伪代码,如果不可能,分享逻辑。