📜  求和为 0 的最大子数组的长度

📅  最后修改于: 2021-10-27 08:17:53             🧑  作者: Mango

给定一个整数数组,找出总和等于 0 的最长子数组的长度。

例子:

Input: arr[] = {15, -2, 2, -8, 1, 7, 10, 23};
Output: 5
Explanation: The longest sub-array with 
elements summing up-to 0 is {-2, 2, -8, 1, 7}

Input: arr[] = {1, 2, 3}
Output: 0
Explanation:There is no subarray with 0 sum

Input:  arr[] = {1, 0, 3}
Output:  1
Explanation: The longest sub-array with 
elements summing up-to 0 is {0}

朴素的方法这涉及在使用两个嵌套循环的情况下使用蛮力。外循环用于固定子数组的起始位置,内循环用于子数组的结束位置,如果元素之和为零,则增加计数。

算法:

  1. 一一考虑所有子数组并检查每个子数组的总和。
  2. 运行两个循环:外循环选择起点 i,内循环尝试从 i 开始的所有子数组。

执行:

C++
/* A simple C++ program to find
largest subarray with 0 sum */
#include 
using namespace std;
 
// Returns length of the largest
// subarray with 0 sum
int maxLen(int arr[], int n)
{
    // Initialize result
    int max_len = 0;
 
    // Pick a starting point
    for (int i = 0; i < n; i++) {
 
        // Initialize currr_sum for
        // every starting point
        int curr_sum = 0;
 
        // try all subarrays starting with 'i'
        for (int j = i; j < n; j++) {
            curr_sum += arr[j];
 
            // If curr_sum becomes 0,
            // then update max_len
            // if required
            if (curr_sum == 0)
                max_len = max(max_len, j - i + 1);
        }
    }
    return max_len;
}
 
// Driver Code
int main()
{
    int arr[] = { 15, -2, 2, -8, 1, 7, 10, 23 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "Length of the longest 0 sum subarray is "
         << maxLen(arr, n);
    return 0;
}


Java
// Java code to find the largest subarray
// with 0 sum
class GFG {
    // Returns length of the largest subarray
    // with 0 sum
    static int maxLen(int arr[], int n)
    {
        int max_len = 0;
 
        // Pick a starting point
        for (int i = 0; i < n; i++) {
            // Initialize curr_sum for every
            // starting point
            int curr_sum = 0;
 
            // try all subarrays starting with 'i'
            for (int j = i; j < n; j++) {
                curr_sum += arr[j];
 
                // If curr_sum becomes 0, then update
                // max_len
                if (curr_sum == 0)
                    max_len = Math.max(max_len, j - i + 1);
            }
        }
        return max_len;
    }
 
    public static void main(String args[])
    {
        int arr[] = { 15, -2, 2, -8, 1, 7, 10, 23 };
        int n = arr.length;
        System.out.println("Length of the longest 0 sum "
                           + "subarray is " + maxLen(arr, n));
    }
}
// This code is contributed by Kamal Rawal


Python
# Python program to find the length of largest subarray with 0 sum
 
# returns the length
def maxLen(arr):
     
    # initialize result
    max_len = 0
 
    # pick a starting point
    for i in range(len(arr)):
         
        # initialize sum for every starting point
        curr_sum = 0
         
        # try all subarrays starting with 'i'
        for j in range(i, len(arr)):
         
            curr_sum += arr[j]
 
            # if curr_sum becomes 0, then update max_len
            if curr_sum == 0:
                max_len = max(max_len, j-i + 1)
 
    return max_len
 
 
# test array
arr = [15, -2, 2, -8, 1, 7, 10, 13]
 
print "Length of the longest 0 sum subarray is % d" % maxLen(arr)


C#
// C# code to find the largest
// subarray with 0 sum
using System;
 
class GFG {
    // Returns length of the
    // largest subarray with 0 sum
    static int maxLen(int[] arr, int n)
    {
        int max_len = 0;
 
        // Pick a starting point
        for (int i = 0; i < n; i++) {
            // Initialize curr_sum
            // for every starting point
            int curr_sum = 0;
 
            // try all subarrays
            // starting with 'i'
            for (int j = i; j < n; j++) {
                curr_sum += arr[j];
 
                // If curr_sum becomes 0,
                // then update max_len
                if (curr_sum == 0)
                    max_len = Math.Max(max_len,
                                       j - i + 1);
            }
        }
        return max_len;
    }
 
    // Driver code
    static public void Main()
    {
        int[] arr = { 15, -2, 2, -8,
                      1, 7, 10, 23 };
        int n = arr.Length;
        Console.WriteLine("Length of the longest 0 sum "
                          + "subarray is " + maxLen(arr, n));
    }
}
 
// This code is contributed by ajit


PHP


Javascript


C++
// C++ program to find the length of largest subarray
// with 0 sum
#include 
using namespace std;
 
// Returns Length of the required subarray
int maxLen(int arr[], int n)
{
    // Map to store the previous sums
    unordered_map presum;
 
    int sum = 0; // Initialize the sum of elements
    int max_len = 0; // Initialize result
 
    // Traverse through the given array
    for (int i = 0; i < n; i++) {
        // Add current element to sum
        sum += arr[i];
 
        if (arr[i] == 0 && max_len == 0)
            max_len = 1;
        if (sum == 0)
            max_len = i + 1;
 
        // Look for this sum in Hash table
        if (presum.find(sum) != presum.end()) {
            // If this sum is seen before, then update max_len
            max_len = max(max_len, i - presum[sum]);
        }
        else {
            // Else insert this sum with index in hash table
            presum[sum] = i;
        }
    }
 
    return max_len;
}
 
// Driver Code
int main()
{
    int arr[] = { 15, -2, 2, -8, 1, 7, 10, 23 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "Length of the longest 0 sum subarray is "
         << maxLen(arr, n);
 
    return 0;
}


Java
// A Java program to find maximum length subarray with 0 sum
import java.util.HashMap;
 
class MaxLenZeroSumSub {
 
    // Returns length of the maximum length subarray with 0 sum
    static int maxLen(int arr[])
    {
        // Creates an empty hashMap hM
        HashMap hM = new HashMap();
 
        int sum = 0; // Initialize sum of elements
        int max_len = 0; // Initialize result
 
        // Traverse through the given array
        for (int i = 0; i < arr.length; i++) {
            // Add current element to sum
            sum += arr[i];
 
            if (arr[i] == 0 && max_len == 0)
                max_len = 1;
 
            if (sum == 0)
                max_len = i + 1;
 
            // Look this sum in hash table
            Integer prev_i = hM.get(sum);
 
            // If this sum is seen before, then update max_len
            // if required
            if (prev_i != null)
                max_len = Math.max(max_len, i - prev_i);
            else // Else put this sum in hash table
                hM.put(sum, i);
        }
 
        return max_len;
    }
 
    // Drive method
    public static void main(String arg[])
    {
        int arr[] = { 15, -2, 2, -8, 1, 7, 10, 23 };
        System.out.println("Length of the longest 0 sum subarray is "
                           + maxLen(arr));
    }
}


Python
# A python program to find maximum length subarray
# with 0 sum in o(n) time
 
# Returns the maximum length
def maxLen(arr):
     
    # NOTE: Dictonary in python in implemented as Hash Maps
    # Create an empty hash map (dictionary)
    hash_map = {}
 
    # Initialize result
    max_len = 0
 
    # Initialize sum of elements
    curr_sum = 0
 
    # Traverse through the given array
    for i in range(len(arr)):
         
        # Add the current element to the sum
        curr_sum += arr[i]
 
        if arr[i] is 0 and max_len is 0:
            max_len = 1
 
        if curr_sum is 0:
            max_len = i + 1
 
        # NOTE: 'in' operation in dictionary to search
        # key takes O(1). Look if current sum is seen
        # before
        if curr_sum in hash_map:
            max_len = max(max_len, i - hash_map[curr_sum] )
        else:
 
            # else put this sum in dictionary
            hash_map[curr_sum] = i
 
    return max_len
 
 
# test array
arr = [15, -2, 2, -8, 1, 7, 10, 13]
  
print "Length of the longest 0 sum subarray is % d" % maxLen(arr)


C#
// C# program to find maximum
// length subarray with 0 sum
using System;
using System.Collections.Generic;
 
public class MaxLenZeroSumSub {
 
    // Returns length of the maximum
    // length subarray with 0 sum
    static int maxLen(int[] arr)
    {
        // Creates an empty hashMap hM
        Dictionary hM = new Dictionary();
 
        int sum = 0; // Initialize sum of elements
        int max_len = 0; // Initialize result
 
        // Traverse through the given array
        for (int i = 0; i < arr.GetLength(0); i++) {
            // Add current element to sum
            sum += arr[i];
 
            if (arr[i] == 0 && max_len == 0)
                max_len = 1;
 
            if (sum == 0)
                max_len = i + 1;
 
            // Look this sum in hash table
            int prev_i = 0;
            if (hM.ContainsKey(sum)) {
                prev_i = hM[sum];
            }
 
            // If this sum is seen before, then update max_len
            // if required
            if (hM.ContainsKey(sum))
                max_len = Math.Max(max_len, i - prev_i);
            else {
                // Else put this sum in hash table
                if (hM.ContainsKey(sum))
                    hM.Remove(sum);
 
                hM.Add(sum, i);
            }
        }
 
        return max_len;
    }
 
    // Driver code
    public static void Main()
    {
        int[] arr = { 15, -2, 2, -8, 1, 7, 10, 23 };
        Console.WriteLine("Length of the longest 0 sum subarray is "
                          + maxLen(arr));
    }
}
 
/* This code contributed by PrinciRaj1992 */


Javascript


输出:

Length of the longest 0 sum subarray is 5

复杂度分析:

  • 时间复杂度:O(n^2) 由于使用了嵌套循环。
  • 空间复杂度:O(1),因为没有使用额外的空间。

有效方法蛮力解决方案是计算每个子阵列的总和并检查总和是否为零。现在让我们尝试通过占用 ‘n’ 长度的额外空间来提高时间复杂度。新数组将存储直到该索引的所有元素的总和。 sum-index 对将存储在hash-map 中哈希映射允许在恒定时间内插入和删除键值对。因此,时间复杂度不受影响。因此,如果相同的值在数组中出现两次,则可以保证特定数组将是零和子数组。

数学证明:

算法:

  1. 创建一个额外的空间、一个长度为 n (prefix)的数组、一个变量 (sum)长度 (max_len)一个哈希映射 (hm)以将 sum-index 对存储为键值对。
  2. 沿着输入数组从开始到结束移动。
  3. 对于每个索引,更新sum = sum + array[i] 的值。
  4. 检查每个索引,如果当前和是否存在于哈希映射中。
  5. 如果存在,将max_len的值更新为两个索引(当前索引和哈希映射中的索引)和max_len 的最大差值。
  6. 否则,将值(和)放入哈希映射中,索引作为键值对。
  7. 打印最大长度(max_len)。

以下是上述方法的试运行:

执行:

C++

// C++ program to find the length of largest subarray
// with 0 sum
#include 
using namespace std;
 
// Returns Length of the required subarray
int maxLen(int arr[], int n)
{
    // Map to store the previous sums
    unordered_map presum;
 
    int sum = 0; // Initialize the sum of elements
    int max_len = 0; // Initialize result
 
    // Traverse through the given array
    for (int i = 0; i < n; i++) {
        // Add current element to sum
        sum += arr[i];
 
        if (arr[i] == 0 && max_len == 0)
            max_len = 1;
        if (sum == 0)
            max_len = i + 1;
 
        // Look for this sum in Hash table
        if (presum.find(sum) != presum.end()) {
            // If this sum is seen before, then update max_len
            max_len = max(max_len, i - presum[sum]);
        }
        else {
            // Else insert this sum with index in hash table
            presum[sum] = i;
        }
    }
 
    return max_len;
}
 
// Driver Code
int main()
{
    int arr[] = { 15, -2, 2, -8, 1, 7, 10, 23 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "Length of the longest 0 sum subarray is "
         << maxLen(arr, n);
 
    return 0;
}

Java

// A Java program to find maximum length subarray with 0 sum
import java.util.HashMap;
 
class MaxLenZeroSumSub {
 
    // Returns length of the maximum length subarray with 0 sum
    static int maxLen(int arr[])
    {
        // Creates an empty hashMap hM
        HashMap hM = new HashMap();
 
        int sum = 0; // Initialize sum of elements
        int max_len = 0; // Initialize result
 
        // Traverse through the given array
        for (int i = 0; i < arr.length; i++) {
            // Add current element to sum
            sum += arr[i];
 
            if (arr[i] == 0 && max_len == 0)
                max_len = 1;
 
            if (sum == 0)
                max_len = i + 1;
 
            // Look this sum in hash table
            Integer prev_i = hM.get(sum);
 
            // If this sum is seen before, then update max_len
            // if required
            if (prev_i != null)
                max_len = Math.max(max_len, i - prev_i);
            else // Else put this sum in hash table
                hM.put(sum, i);
        }
 
        return max_len;
    }
 
    // Drive method
    public static void main(String arg[])
    {
        int arr[] = { 15, -2, 2, -8, 1, 7, 10, 23 };
        System.out.println("Length of the longest 0 sum subarray is "
                           + maxLen(arr));
    }
}

Python

# A python program to find maximum length subarray
# with 0 sum in o(n) time
 
# Returns the maximum length
def maxLen(arr):
     
    # NOTE: Dictonary in python in implemented as Hash Maps
    # Create an empty hash map (dictionary)
    hash_map = {}
 
    # Initialize result
    max_len = 0
 
    # Initialize sum of elements
    curr_sum = 0
 
    # Traverse through the given array
    for i in range(len(arr)):
         
        # Add the current element to the sum
        curr_sum += arr[i]
 
        if arr[i] is 0 and max_len is 0:
            max_len = 1
 
        if curr_sum is 0:
            max_len = i + 1
 
        # NOTE: 'in' operation in dictionary to search
        # key takes O(1). Look if current sum is seen
        # before
        if curr_sum in hash_map:
            max_len = max(max_len, i - hash_map[curr_sum] )
        else:
 
            # else put this sum in dictionary
            hash_map[curr_sum] = i
 
    return max_len
 
 
# test array
arr = [15, -2, 2, -8, 1, 7, 10, 13]
  
print "Length of the longest 0 sum subarray is % d" % maxLen(arr)

C#

// C# program to find maximum
// length subarray with 0 sum
using System;
using System.Collections.Generic;
 
public class MaxLenZeroSumSub {
 
    // Returns length of the maximum
    // length subarray with 0 sum
    static int maxLen(int[] arr)
    {
        // Creates an empty hashMap hM
        Dictionary hM = new Dictionary();
 
        int sum = 0; // Initialize sum of elements
        int max_len = 0; // Initialize result
 
        // Traverse through the given array
        for (int i = 0; i < arr.GetLength(0); i++) {
            // Add current element to sum
            sum += arr[i];
 
            if (arr[i] == 0 && max_len == 0)
                max_len = 1;
 
            if (sum == 0)
                max_len = i + 1;
 
            // Look this sum in hash table
            int prev_i = 0;
            if (hM.ContainsKey(sum)) {
                prev_i = hM[sum];
            }
 
            // If this sum is seen before, then update max_len
            // if required
            if (hM.ContainsKey(sum))
                max_len = Math.Max(max_len, i - prev_i);
            else {
                // Else put this sum in hash table
                if (hM.ContainsKey(sum))
                    hM.Remove(sum);
 
                hM.Add(sum, i);
            }
        }
 
        return max_len;
    }
 
    // Driver code
    public static void Main()
    {
        int[] arr = { 15, -2, 2, -8, 1, 7, 10, 23 };
        Console.WriteLine("Length of the longest 0 sum subarray is "
                          + maxLen(arr));
    }
}
 
/* This code contributed by PrinciRaj1992 */

Javascript


输出:

Length of the longest 0 sum subarray is 5

复杂度分析:

  • 时间复杂度: O(n),由于使用了良好的散列函数,将允许在 O(1) 时间内进行插入和检索操作。
  • 空间复杂度: O(n),用于使用额外空间来存储前缀数组和哈希图。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程