📜  查找总和最接近0的子数组

📅  最后修改于: 2021-04-27 19:41:19             🧑  作者: Mango

给定正负数数组,任务是找出总和最接近0的子数组。
可以有多个这样的子数组,我们只需要输出其中之一即可。
例子:

Input : arr[] = {-1, 3, 2, -5, 4}
Output : 1, 3
Subarray from index 1 to 3 has sum closest to 0 i.e.
3 + 2 + -5 = 0

Input : {2, -5, 4, -6, 3} 
Output : 0, 2
2 + -5 + 4 = 1 closest to 0

提问人:微软

幼稚的方法是一一考虑所有子阵列,并更新总和最接近0的子阵列索引。

C++
// C++ program to find subarray with
// sum closest to 0
#include 
using namespace std;
  
// Function to find the subarray
pair findSubArray(int arr[], int n)
{
  
    int start, end, min_sum = INT_MAX;
  
    // Pick a starting point
    for (int i = 0; i < n; i++) {
  
        // Consider current starting point
        // as a subarray and update minimum
        // sum and subarray indexes
        int curr_sum = arr[i];
        if (min_sum > abs(curr_sum)) {
            min_sum = abs(curr_sum);
            start = i;
            end = i;
        }
  
        // Try all subarrays starting with i
        for (int j = i + 1; j < n; j++) {
            curr_sum = curr_sum + arr[j];
  
            // update minimum sum
            // and subarray indexes
            if (min_sum > abs(curr_sum)) {
                min_sum = abs(curr_sum);
                start = i;
                end = j;
            }
        }
    }
  
    // Return starting and ending indexes
    pair p = make_pair(start, end);
    return p;
}
  
// Drivers code
int main()
{
    int arr[] = { 2, -5, 4, -6, -3 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    pair point = findSubArray(arr, n);
    cout << "Subarray starting from ";
    cout << point.first << " to " << point.second;
    return 0;
}


Java
// Java program to find subarray with
// sum closest to 0
  
class GFG
{
  
    static class Pair 
    {
  
        int first, second;
        public Pair(int first, int second)
        {
            this.first = first;
            this.second = second;
        }
  
    }
      
    // Function to find the subarray
    static Pair findSubArray(int arr[], int n)
    {
  
        int start = 0, end = 0, min_sum = Integer.MAX_VALUE;
  
        // Pick a starting point
        for (int i = 0; i < n; i++)
        {
  
            // Consider current starting point
            // as a subarray and update minimum
            // sum and subarray indexes
            int curr_sum = arr[i];
            if (min_sum > Math.abs(curr_sum)) 
            {
                min_sum = Math.abs(curr_sum);
                start = i;
                end = i;
            }
  
            // Try all subarrays starting with i
            for (int j = i + 1; j < n; j++) 
            {
                curr_sum = curr_sum + arr[j];
  
                // update minimum sum
                // and subarray indexes
                if (min_sum > Math.abs(curr_sum)) 
                {
                    min_sum = Math.abs(curr_sum);
                    start = i;
                    end = j;
                }
            }
        }
  
        // Return starting and ending indexes
        Pair p = new Pair(start, end);
        return p;
    }
  
    // Drivers code
    public static void main(String[] args) 
    {
        int arr[] = {2, -5, 4, -6, -3};
        int n = arr.length;
  
        Pair point = findSubArray(arr, n);
        System.out.println("Subarray starting from "
                + point.first + " to " + point.second);
    }
}
  
// This code has been contributed by 29AjayKumar


Python3
# Python 3 program to find subarray with
# sum closest to 0
import sys
  
# Function to find the subarray
def findSubArray(arr, n):
    min_sum = sys.maxsize
  
    # Pick a starting point
    for i in range(n):
          
        # Consider current starting point
        # as a subarray and update minimum
        # sum and subarray indexes
        curr_sum = arr[i]
        if (min_sum > abs(curr_sum)):
            min_sum = abs(curr_sum)
            start = i
            end = i
  
        # Try all subarrays starting with i
        for j in range(i + 1, n, 1):
            curr_sum = curr_sum + arr[j]
  
            # update minimum sum
            # and subarray indexes
            if (min_sum > abs(curr_sum)):
                min_sum = abs(curr_sum)
                start = i
                end = j
  
    # Return starting and ending indexes
    p = [start, end]
    return p
  
# Driver Code
if __name__ == '__main__':
    arr = [2, -5, 4, -6, -3]
    n = len(arr)
  
    point = findSubArray(arr, n)
    print("Subarray starting from ", end = "")
    print(point[0], "to", point[1])
  
# This code is contributed by
# Surendra_Gangwar


C#
// C# program to find subarray with
// sum closest to 0
using System;
      
class GFG
{
  
    public class Pair 
    {
  
        public int first, second;
        public Pair(int first, int second)
        {
            this.first = first;
            this.second = second;
        }
  
    }
      
    // Function to find the subarray
    static Pair findSubArray(int []arr, int n)
    {
  
        int start = 0, end = 0, min_sum = int.MaxValue;
  
        // Pick a starting point
        for (int i = 0; i < n; i++)
        {
  
            // Consider current starting point
            // as a subarray and update minimum
            // sum and subarray indexes
            int curr_sum = arr[i];
            if (min_sum > Math.Abs(curr_sum)) 
            {
                min_sum = Math.Abs(curr_sum);
                start = i;
                end = i;
            }
  
            // Try all subarrays starting with i
            for (int j = i + 1; j < n; j++) 
            {
                curr_sum = curr_sum + arr[j];
  
                // update minimum sum
                // and subarray indexes
                if (min_sum > Math.Abs(curr_sum)) 
                {
                    min_sum = Math.Abs(curr_sum);
                    start = i;
                    end = j;
                }
            }
        }
  
        // Return starting and ending indexes
        Pair p = new Pair(start, end);
        return p;
    }
  
    // Drivers code
    public static void Main(String[] args) 
    {
        int []arr = {2, -5, 4, -6, -3};
        int n = arr.Length;
  
        Pair point = findSubArray(arr, n);
        Console.WriteLine("Subarray starting from "
                + point.first + " to " + point.second);
    }
}
  
// This code is contributed by Princi Singh


C++
// C++ program to find subarray with sum 
// closest to 0
#include 
using namespace std;
  
struct prefix {
    int sum;
    int index;
};
  
// Sort on the basis of sum
bool comparison(prefix a, prefix b)
{
    return a.sum < b.sum;
}
  
// Returns subarray with sum closest to 0. 
pair findSubArray(int arr[], int n)
{
    int start, end, min_diff = INT_MAX;
  
    prefix pre_sum[n + 1];
  
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    for (int i = 1; i <= n; i++) {
        pre_sum[i].sum = pre_sum[i-1].sum + arr[i-1];
        pre_sum[i].index = i - 1;
    }
  
    // Sort on the basis of sum
    sort(pre_sum, pre_sum + (n + 1), comparison);
  
    // Find two consecutive elements with minimum difference
    for (int i = 1; i <= n; i++) {
        int diff = pre_sum[i].sum - pre_sum[i-1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff) {
            min_diff = diff;
            start = pre_sum[i-1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    pair p = make_pair(start + 1, end);
    return p;
}
  
// Drivers code
int main()
{
    int arr[] = { 2, 3, -4, -1, 6 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    pair point = findSubArray(arr, n);
    cout << "Subarray starting from ";
    cout << point.first << " to " << point.second;
  
    return 0;
}


Java
// Java program to find subarray with sum
// closest to 0
import java.util.*;
  
class Prefix 
{
    int sum, index;
}
  
class Pair
{
    int first, second;
    Pair(int a, int b)
    {
        first = a;
        second = b;
    }
}
  
class GFG{
  
// Returns subarray with sum closest to 0.
static Pair findSubArray(int arr[], int n)
{
    int start = -1, end = -1,
     min_diff = Integer.MAX_VALUE;
  
    Prefix pre_sum[] = new Prefix[n + 1];
    for(int i = 0; i < n + 1; i++)
        pre_sum[i] = new Prefix();
          
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    for(int i = 1; i <= n; i++) 
    {
        pre_sum[i].sum = pre_sum[i - 1].sum +
                             arr[i - 1];
        pre_sum[i].index = i - 1;
    }
  
    // Sort on the basis of sum
    Arrays.sort(pre_sum, ((a, b) -> a.sum - b.sum));
  
    // Find two consecutive elements with minimum
    // difference
    for(int i = 1; i <= n; i++) 
    {
        int diff = pre_sum[i].sum - 
                   pre_sum[i - 1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff)
        {
            min_diff = diff;
            start = pre_sum[i - 1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    Pair p = new Pair(start + 1, end);
    return p;
}
  
// Driver code
public static void main(String[] args)
{
    int arr[] = { 2, 3, -4, -1, 6 };
    int n = arr.length;
  
    Pair point = findSubArray(arr, n);
      
    System.out.print("Subarray starting from ");
    System.out.println(point.first + " to " + 
                       point.second);
}
}
  
// This code is contributed by jrishabh99


Python3
# Python3 program to find subarray 
# with sum closest to 0 
class prefix:
      
    def __init__(self, sum, index):
        self.sum = sum
        self.index = index
  
# Returns subarray with sum closest to 0. 
def findSubArray(arr, n): 
  
    start, end, min_diff = None, None, float('inf') 
  
    pre_sum = [None] * (n + 1)
  
    # To consider the case of subarray 
    # starting from beginning of the array 
    pre_sum[0] = prefix(0, -1)
  
    # Store prefix sum with index 
    for i in range(1, n + 1): 
        pre_sum[i] = prefix(pre_sum[i - 1].sum + 
                                arr[i - 1], i - 1) 
  
    # Sort on the basis of sum 
    pre_sum.sort(key = lambda x: x.sum)
  
    # Find two consecutive elements 
    # with minimum difference 
    for i in range(1, n + 1): 
        diff = pre_sum[i].sum - pre_sum[i - 1].sum
  
        # Update minimum difference 
        # and starting and ending indexes 
        if min_diff > diff: 
            min_diff = diff 
            start = pre_sum[i - 1].index 
            end = pre_sum[i].index 
          
    # Return starting and ending indexes 
    return (start + 1, end) 
  
# Driver code 
if __name__ == "__main__": 
  
    arr = [2, 3, -4, -1, 6] 
    n = len(arr) 
  
    point = findSubArray(arr, n) 
    print("Subarray starting from", 
           point[0], "to", point[1]) 
  
# This code is contributed by Rituraj Jain


输出:

Subarray starting from 0 to 2

时间复杂度: O(n 2 )

一种有效的方法是执行以下步骤:

  1. 维护一个前缀求和数组。还要在前缀和数组中维护索引。
  2. 根据总和对前缀总和数组进行排序。
  3. 在前缀和数组中找到具有最小差异的两个元素。
    i.e.  Find min(pre_sum[i] - pre_sum[i-1]) 
  4. 返回具有最小差异的pre_sum索引。
  5. 具有(lower_index + 1,upper_index)的子数组的总和最接近0。
  6. 采用lower_index + 1,因为在lower_index上减去值后,我们得到的总和最接近0。这就是为什么不必包含lower_index的原因。

C++

// C++ program to find subarray with sum 
// closest to 0
#include 
using namespace std;
  
struct prefix {
    int sum;
    int index;
};
  
// Sort on the basis of sum
bool comparison(prefix a, prefix b)
{
    return a.sum < b.sum;
}
  
// Returns subarray with sum closest to 0. 
pair findSubArray(int arr[], int n)
{
    int start, end, min_diff = INT_MAX;
  
    prefix pre_sum[n + 1];
  
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    for (int i = 1; i <= n; i++) {
        pre_sum[i].sum = pre_sum[i-1].sum + arr[i-1];
        pre_sum[i].index = i - 1;
    }
  
    // Sort on the basis of sum
    sort(pre_sum, pre_sum + (n + 1), comparison);
  
    // Find two consecutive elements with minimum difference
    for (int i = 1; i <= n; i++) {
        int diff = pre_sum[i].sum - pre_sum[i-1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff) {
            min_diff = diff;
            start = pre_sum[i-1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    pair p = make_pair(start + 1, end);
    return p;
}
  
// Drivers code
int main()
{
    int arr[] = { 2, 3, -4, -1, 6 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    pair point = findSubArray(arr, n);
    cout << "Subarray starting from ";
    cout << point.first << " to " << point.second;
  
    return 0;
}

Java

// Java program to find subarray with sum
// closest to 0
import java.util.*;
  
class Prefix 
{
    int sum, index;
}
  
class Pair
{
    int first, second;
    Pair(int a, int b)
    {
        first = a;
        second = b;
    }
}
  
class GFG{
  
// Returns subarray with sum closest to 0.
static Pair findSubArray(int arr[], int n)
{
    int start = -1, end = -1,
     min_diff = Integer.MAX_VALUE;
  
    Prefix pre_sum[] = new Prefix[n + 1];
    for(int i = 0; i < n + 1; i++)
        pre_sum[i] = new Prefix();
          
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    for(int i = 1; i <= n; i++) 
    {
        pre_sum[i].sum = pre_sum[i - 1].sum +
                             arr[i - 1];
        pre_sum[i].index = i - 1;
    }
  
    // Sort on the basis of sum
    Arrays.sort(pre_sum, ((a, b) -> a.sum - b.sum));
  
    // Find two consecutive elements with minimum
    // difference
    for(int i = 1; i <= n; i++) 
    {
        int diff = pre_sum[i].sum - 
                   pre_sum[i - 1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff)
        {
            min_diff = diff;
            start = pre_sum[i - 1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    Pair p = new Pair(start + 1, end);
    return p;
}
  
// Driver code
public static void main(String[] args)
{
    int arr[] = { 2, 3, -4, -1, 6 };
    int n = arr.length;
  
    Pair point = findSubArray(arr, n);
      
    System.out.print("Subarray starting from ");
    System.out.println(point.first + " to " + 
                       point.second);
}
}
  
// This code is contributed by jrishabh99

Python3

# Python3 program to find subarray 
# with sum closest to 0 
class prefix:
      
    def __init__(self, sum, index):
        self.sum = sum
        self.index = index
  
# Returns subarray with sum closest to 0. 
def findSubArray(arr, n): 
  
    start, end, min_diff = None, None, float('inf') 
  
    pre_sum = [None] * (n + 1)
  
    # To consider the case of subarray 
    # starting from beginning of the array 
    pre_sum[0] = prefix(0, -1)
  
    # Store prefix sum with index 
    for i in range(1, n + 1): 
        pre_sum[i] = prefix(pre_sum[i - 1].sum + 
                                arr[i - 1], i - 1) 
  
    # Sort on the basis of sum 
    pre_sum.sort(key = lambda x: x.sum)
  
    # Find two consecutive elements 
    # with minimum difference 
    for i in range(1, n + 1): 
        diff = pre_sum[i].sum - pre_sum[i - 1].sum
  
        # Update minimum difference 
        # and starting and ending indexes 
        if min_diff > diff: 
            min_diff = diff 
            start = pre_sum[i - 1].index 
            end = pre_sum[i].index 
          
    # Return starting and ending indexes 
    return (start + 1, end) 
  
# Driver code 
if __name__ == "__main__": 
  
    arr = [2, 3, -4, -1, 6] 
    n = len(arr) 
  
    point = findSubArray(arr, n) 
    print("Subarray starting from", 
           point[0], "to", point[1]) 
  
# This code is contributed by Rituraj Jain

输出:

Subarray starting from 0 to 3

时间复杂度: O(n log n)

参考:
https://www.careercup.com/question?id=14583859