📌  相关文章
📜  用于查找具有给定总和的子数组的Java程序 - 集合 1(非负数)

📅  最后修改于: 2022-05-13 01:57:50.888000             🧑  作者: Mango

用于查找具有给定总和的子数组的Java程序 - 集合 1(非负数)

给定一个未排序的非负整数数组,找到一个与给定数字相加的连续子数组。
例子 :

Input: arr[] = {1, 4, 20, 3, 10, 5}, sum = 33
Output: Sum found between indexes 2 and 4
Sum of elements between indices
2 and 4 is 20 + 3 + 10 = 33

Input: arr[] = {1, 4, 0, 0, 3, 10, 5}, sum = 7
Output: Sum found between indexes 1 and 4
Sum of elements between indices
1 and 4 is 4 + 0 + 0 + 3 = 7

Input: arr[] = {1, 4}, sum = 0
Output: No subarray found
There is no subarray with 0 sum

可能有多个子数组以 sum 作为给定的总和。以下解决方案首先打印这样的子数组。

简单方法:一个简单的解决方案是逐个考虑所有子数组并检查每个子数组的总和。以下程序实现了简单的解决方案。运行两个循环:外循环选择起点 I,内循环尝试从 i 开始的所有子数组。
算法:

  1. 从头到尾遍历数组。
  2. 从每个索引开始另一个从i到数组末尾的循环以获取从 i 开始的所有子数组,并保留一个变量 sum 来计算总和。
  3. 对于内部循环中的每个索引更新sum = sum + array[j]
  4. 如果总和等于给定的总和,则打印子数组。
Java
// Java program to implement
// the above approach
class SubarraySum 
{
    /* Returns true if the there is a 
       subarray of arr[] with a sum equal 
       to 'sum' otherwise returns false. 
       Also, prints the result */
    int subArraySum(int arr[], int n, 
                    int sum)
    {
        int curr_sum, i, j;
  
        // Pick a starting point
        for (i = 0; i < n; i++) 
        {
            curr_sum = arr[i];
  
            // Try all subarrays starting with 'i'
            for (j = i + 1; j <= n; j++) 
            {
                if (curr_sum == sum) 
                {
                    int p = j - 1;
                    System.out.println(
                     "Sum found between indexes " + 
                      i + " and " + p);
                    return 1;
                }
                if (curr_sum > sum || j == n)
                    break;
                curr_sum = curr_sum + arr[j];
            }
        }
        System.out.println("No subarray found");
        return 0;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        SubarraySum arraysum = 
                    new SubarraySum();
        int arr[] = {15, 2, 4, 8, 
                     9, 5, 10, 23 };
        int n = arr.length;
        int sum = 23;
        arraysum.subArraySum(arr, n, sum);
    }
}
// This code is contributed by Mayank Jaiswal(mayank_24)


Java
// Java program to implement
// the above approach
class SubarraySum 
{
    /* Returns true if the there is a 
       subarray of arr[] with sum equal 
       to 'sum' otherwise returns false.  
       Also, prints the result */
    int subArraySum(int arr[], int n, 
                    int sum)
    {
        int curr_sum = arr[0], start = 0, i;
  
        // Pick a starting point
        for (i = 1; i <= n; i++) 
        {
            // If curr_sum exceeds the sum,
            // then remove the starting elements
            while (curr_sum > sum && start < i - 1) 
            {
                curr_sum = curr_sum - arr[start];
                start++;
            }
            // If curr_sum becomes equal to sum,
            // then return true
            if (curr_sum == sum) 
            {
                int p = i - 1;
                System.out.println(
                "Sum found between indexes " + 
                 start + " and " + p);
                return 1;
            }
            // Add this element to curr_sum
            if (i < n)
                curr_sum = curr_sum + arr[i];
        }
        System.out.println("No subarray found");
        return 0;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        SubarraySum arraysum = 
                    new SubarraySum();
        int arr[] = {15, 2, 4, 8, 
                     9, 5, 10, 23};
        int n = arr.length;
        int sum = 23;
        arraysum.subArraySum(arr, n, sum);
    }
}
// This code is contributed by Mayank Jaiswal(mayank_24)


输出 :

Sum found between indexes 1 and 4

复杂性分析:

  • 时间复杂度:最坏情况下为 O(n^2)。
    嵌套循环用于遍历数组,因此时间复杂度为 O(n^2)
  • 空间复杂度: O(1)。
    因为需要恒定的额外空间。

有效方法:如果数组的所有元素都是正数,则有一个想法。如果子数组的总和大于给定总和,则将元素添加到当前子数组的总和不可能是x (给定总和)。想法是对滑动窗口使用类似的方法。从一个空子数组开始,向子数组添加元素,直到总和小于x 。如果总和大于x ,则从当前子数组的开头删除元素。
算法:

  1. 创建三个变量, l=0,sum=0
  2. 从头到尾遍历数组。
  3. 通过添加当前元素来更新变量 sum, sum = sum + array[i]
  4. 如果总和大于给定总和,则将变量 sum 更新为sum = sum – array[l] ,并将 l 更新为 l++。
  5. 如果总和等于给定总和,则打印子数组并中断循环。

Java

// Java program to implement
// the above approach
class SubarraySum 
{
    /* Returns true if the there is a 
       subarray of arr[] with sum equal 
       to 'sum' otherwise returns false.  
       Also, prints the result */
    int subArraySum(int arr[], int n, 
                    int sum)
    {
        int curr_sum = arr[0], start = 0, i;
  
        // Pick a starting point
        for (i = 1; i <= n; i++) 
        {
            // If curr_sum exceeds the sum,
            // then remove the starting elements
            while (curr_sum > sum && start < i - 1) 
            {
                curr_sum = curr_sum - arr[start];
                start++;
            }
            // If curr_sum becomes equal to sum,
            // then return true
            if (curr_sum == sum) 
            {
                int p = i - 1;
                System.out.println(
                "Sum found between indexes " + 
                 start + " and " + p);
                return 1;
            }
            // Add this element to curr_sum
            if (i < n)
                curr_sum = curr_sum + arr[i];
        }
        System.out.println("No subarray found");
        return 0;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        SubarraySum arraysum = 
                    new SubarraySum();
        int arr[] = {15, 2, 4, 8, 
                     9, 5, 10, 23};
        int n = arr.length;
        int sum = 23;
        arraysum.subArraySum(arr, n, sum);
    }
}
// This code is contributed by Mayank Jaiswal(mayank_24)

输出 :

Sum found between indexes 1 and 4

复杂性分析:

  • 时间复杂度: O(n)。
    只需要遍历一次数组。所以时间复杂度是O(n)。
  • 空间复杂度: O(1)。
    因为需要恒定的额外空间。

请参考完整的文章 Find subarray with given sum |设置 1(非负数)了解更多详情!