📌  相关文章
📜  使用给定总和查找子数组的 C++ 程序 – 集合 1(非负数)

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

使用给定总和查找子数组的 C++ 程序 – 集合 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. 如果总和等于给定的总和,则打印子数组。
C++
/* C++ simple program to print 
   subarray with sum as given sum */
#include 
using namespace std;
  
/* 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, 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) 
            {
                cout << "Sum found between indexes " << 
                         i << " and " << j - 1;
                return 1;
            }
            if (curr_sum > sum || j == n)
                break;
            curr_sum = curr_sum + arr[j];
        }
    }
    cout << "No subarray found";
    return 0;
}
  
// Driver Code
int main()
{
    int arr[] = {15, 2, 4, 8, 
                 9, 5, 10, 23};
    int n = sizeof(arr) / sizeof(arr[0]);
    int sum = 23;
    subArraySum(arr, n, sum);
    return 0;
}
// This code is contributed by rathbhupendra


C++
/* An efficient program to print 
subarray with sum as given sum */
#include 
using namespace std;
  
/* 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)
{
    /* Initialize curr_sum as value of 
       first element and starting point as 0 */
    int curr_sum = arr[0], start = 0, i;
  
    /* Add elements one by one to curr_sum and 
       if the curr_sum exceeds the sum,
       then remove starting element */
    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) 
        {
            cout << "Sum found between indexes " << 
                     start << " and " << i - 1;
            return 1;
        }
        // Add this element to curr_sum
        if (i < n)
            curr_sum = curr_sum + arr[i];
    }
    // If we reach here, then no subarray
    cout << "No subarray found";
    return 0;
}
  
// Driver Code
int main()
{
    int arr[] = {15, 2, 4, 8, 
                 9, 5, 10, 23};
    int n = sizeof(arr) / sizeof(arr[0]);
    int sum = 23;
    subArraySum(arr, n, sum);
    return 0;
}
// This code is contributed by SHUBHAMSINGH10


输出 :

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. 如果总和等于给定总和,则打印子数组并中断循环。

C++

/* An efficient program to print 
subarray with sum as given sum */
#include 
using namespace std;
  
/* 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)
{
    /* Initialize curr_sum as value of 
       first element and starting point as 0 */
    int curr_sum = arr[0], start = 0, i;
  
    /* Add elements one by one to curr_sum and 
       if the curr_sum exceeds the sum,
       then remove starting element */
    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) 
        {
            cout << "Sum found between indexes " << 
                     start << " and " << i - 1;
            return 1;
        }
        // Add this element to curr_sum
        if (i < n)
            curr_sum = curr_sum + arr[i];
    }
    // If we reach here, then no subarray
    cout << "No subarray found";
    return 0;
}
  
// Driver Code
int main()
{
    int arr[] = {15, 2, 4, 8, 
                 9, 5, 10, 23};
    int n = sizeof(arr) / sizeof(arr[0]);
    int sum = 23;
    subArraySum(arr, n, sum);
    return 0;
}
// This code is contributed by SHUBHAMSINGH10

输出 :

Sum found between indexes 1 and 4

复杂性分析:

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

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