📌  相关文章
📜  总和大于等于零的最长子数组

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

总和大于等于零的最长子数组

给定一个包含 N 个整数的数组。任务是找到最大长度子数组,使得其所有元素的总和大于或等于 0。

例子

Input: arr[]= {-1, 4, -2, -5, 6, -8}
Output: 5
Explanation: {-1, 4, -2, -5, 6} forms the longest subarray with sum=2.

Input: arr[]={-5, -6}
Output: 0
Explanation: No such subarray is possible 

一种朴素的方法是预先计算数组的前缀和。然后对每个开始和结束索引使用两个嵌套循环,如果直到结束索引的前缀和减去开始索引之前的前缀和大于等于 0,则相应地更新答案。
时间复杂度:O(N 2 )

一种有效的方法是使用二分搜索来解决以下问题。以下是解决上述问题的步骤:

  • 首先,计算数组每个索引的后缀和并将其存储在另一个数组中。
  • 使用另一个数组搜索空间来存储每个子数组的起点。
  • 从第 0 个索引开始迭代,如果直到第 i 个索引的后缀大于搜索空间中最顶部的元素,则将该后缀总和添加到搜索空间。
  • 使用二分搜索查找搜索空间中的最低索引,使得直到该索引的后缀总和减去直到 (i+1)'th 的后缀总和大于等于 0。如果存在任何此类索引,则相应地更新答案.

这里的关键观察是,如果后缀总和大于搜索空间中的所有其他后缀总和,则将后缀总和添加到搜索空间,因为必须最大化长度。

下面是上述方法的实现。

C++
// C++ Program to compute the
// longest subarray with
// sum greater than equal to 0.
#include 
using namespace std;
 
// Function for the searching the
// starting index of the subarray
int search(int* searchspace, int s, int e, int key)
{
    // -1 signifies that no
    // starting point of the subarray
    // is not found with sum greater
    // than equal to 0.
    int ans = -1;
 
    // Binary search
    while (s <= e) {
        int mid = (s + e) / 2;
 
        if (searchspace[mid] - key >= 0) {
            ans = mid;
            e = mid - 1;
        }
        else {
            s = mid + 1;
        }
    }
 
    return ans;
}
 
// Function to return the longest subarray
int longestSubarray(int a[], int n)
{
    // Array for the suffix sum
    // of the above the array.
    int SuffixSum[n + 1];
    SuffixSum[n] = 0;
 
    for (int i = n - 1; i >= 0; --i) {
        SuffixSum[i] = SuffixSum[i + 1] + a[i];
    }
 
    int ans = 0;
 
    // Search Space for potential starting
    // points of the subarray.
    // It will store the suffix sum
    // till i'th index in increasing order.
    int searchspace[n];
 
    // It will store the indexes
    // till which the suffix sum
    // is present in search space.
    int index[n];
 
    int j = 0;
 
    for (int i = 0; i < n; ++i) {
 
        // add the element to the search space if the j=0
        // or if the topmost element is lesser
        // than present suffix sum.
        if (j == 0 or SuffixSum[i] > searchspace[j - 1]) {
            searchspace[j] = SuffixSum[i];
            index[j] = i;
            j++;
        }
 
        int idx = search(searchspace, 0, j - 1, SuffixSum[i + 1]);
 
        // Only when idx is not -1 an subarray is
        // possible with ending index at i.
        if (idx != -1)
            ans = max(ans, i - index[idx] + 1);
    }
 
    return ans;
}
 
// Driver Code
int main()
{
    int a[] = { -1, 4, -2, -5, 6, -8 };
 
    int n = sizeof(a) / sizeof(a[0]);
 
    cout << longestSubarray(a, n);
 
    return 0;
}


Java
// Java  Program to compute the
// longest subarray with
// sum greater than equal to 0.
 
import java.io.*;
 
class GFG {
 
 
// Function for the searching the
// starting index of the subarray
static int search(int searchspace[], int s, int e, int key)
{
    // -1 signifies that no
    // starting point of the subarray
    // is not found with sum greater
    // than equal to 0.
    int ans = -1;
 
    // Binary search
    while (s <= e) {
        int mid = (s + e) / 2;
 
        if (searchspace[mid] - key >= 0) {
            ans = mid;
            e = mid - 1;
        }
        else {
            s = mid + 1;
        }
    }
 
    return ans;
}
 
// Function to return the longest subarray
static int longestSubarray(int []a, int n)
{
    // Array for the suffix sum
    // of the above the array.
    int SuffixSum[] = new int[n+1];
    SuffixSum[n] = 0;
 
    for (int i = n - 1; i >= 0; --i) {
        SuffixSum[i] = SuffixSum[i + 1] + a[i];
    }
 
    int ans = 0;
 
    // Search Space for potential starting
    // points of the subarray.
    // It will store the suffix sum
    // till i'th index in increasing order.
    int searchspace[] = new int[n];
 
    // It will store the indexes
    // till which the suffix sum
    // is present in search space.
    int index[] = new int[n];
 
    int j = 0;
 
    for (int i = 0; i < n; ++i) {
 
        // add the element to the search space if the j=0
        // or if the topmost element is lesser
        // than present suffix sum.
        if ((j == 0) || SuffixSum[i] > searchspace[j - 1]) {
            searchspace[j] = SuffixSum[i];
            index[j] = i;
            j++;
        }
 
        int idx = search(searchspace, 0, j - 1, SuffixSum[i + 1]);
 
        // Only when idx is not -1 an subarray is
        // possible with ending index at i.
        if (idx != -1)
            ans = Math.max(ans, i - index[idx] + 1);
    }
 
    return ans;
}
 
// Driver Code
 
 
    public static void main (String[] args) {
            int []a = { -1, 4, -2, -5, 6, -8 };
 
    int n = a.length;
 
    System.out.println(longestSubarray(a, n));
    }
}
// This code is contributed
// by  anuj_67..


Python3
# Python3 program to compute the longest
# with sum greater than equal to 0
import math as mt
 
# function for the searching the
# starting index of the subarray
def search(searchspace, s, e, key):
     
    # -1 signifies that no starting point
    # of the subarray is not found with
    # sum greater than equal to 0.
     
    ans = -1
     
    # Binary search
    while s <= e:
        mid = (s + e) // 2
         
        if searchspace[mid] - key >= 0:
            ans = mid
            e = mid - 1
        else:
            s = mid + 1
    return ans
     
# function to return the longest subarray
def longestSubarray(a, n):
    # Array for the suffix sum of
    # the above the array
    SuffixSum = [0 for i in range(n + 1)]
     
    for i in range(n - 1, -1, -1):
        SuffixSum[i] = SuffixSum[i + 1] + a[i]
     
    ans = 0
     
    # Search Space for potential starting
    # points of the subarray.
    # It will store the suffix sum
    # till i'th index in increasing order
    searchspace = [0 for i in range(n)]
     
    # It will store the indexes
    # till which the suffix sum
    # is present in search space
    index = [0 for i in range(n)]
     
    j = 0
     
    for i in range(n):
         
        # add the element to the search space
        # if the j=0 or if the topmost element
        # is lesser than present suffix sum
        if j == 0 or (SuffixSum[i] >
                      searchspace[j - 1]):
            searchspace[j] = SuffixSum[i]
            index[j] = i
            j += 1
     
        idx = search(searchspace, 0, j - 1,
                     SuffixSum[i + 1])
                      
        # Only when idx is not -1 an subarray is
        # possible with ending index at i.
        if idx != -1:
            ans = max(ans, i - index[idx] + 1)
     
    return ans
 
# Driver Code
a = [-1, 4, -2, -5, 6, -8]
  
n = len(a)
print(longestSubarray(a, n))
 
# This code is contributed
# by Mohit kumar 29


C#
// C#  Program to compute the
// longest subarray with
// sum greater than equal to 0.
  
using System;
  
class GFG {
  
// Function for the searching the
// starting index of the subarray
static int search(int[] searchspace, int s, int e, int key)
{
    // -1 signifies that no
    // starting point of the subarray
    // is not found with sum greater
    // than equal to 0.
    int ans = -1;
  
    // Binary search
    while (s <= e) {
        int mid = (s + e) / 2;
  
        if (searchspace[mid] - key >= 0) {
            ans = mid;
            e = mid - 1;
        }
        else {
            s = mid + 1;
        }
    }
  
    return ans;
}
  
// Function to return the longest subarray
static int longestSubarray(int[] a, int n)
{
    // Array for the suffix sum
    // of the above the array.
    int[] SuffixSum = new int[n+1];
    SuffixSum[n] = 0;
  
    for (int i = n - 1; i >= 0; --i) {
        SuffixSum[i] = SuffixSum[i + 1] + a[i];
    }
  
    int ans = 0;
  
    // Search Space for potential starting
    // points of the subarray.
    // It will store the suffix sum
    // till i'th index in increasing order.
    int[] searchspace = new int[n];
  
    // It will store the indexes
    // till which the suffix sum
    // is present in search space.
    int[] index = new int[n];
  
    int j = 0;
  
    for (int i = 0; i < n; ++i) {
  
        // add the element to the search space if the j=0
        // or if the topmost element is lesser
        // than present suffix sum.
        if ((j == 0) || SuffixSum[i] > searchspace[j - 1]) {
            searchspace[j] = SuffixSum[i];
            index[j] = i;
            j++;
        }
  
        int idx = search(searchspace, 0, j - 1, SuffixSum[i + 1]);
  
        // Only when idx is not -1 an subarray is
        // possible with ending index at i.
        if (idx != -1)
            ans = Math.Max(ans, i - index[idx] + 1);
    }
  
    return ans;
}
  
// Driver Code
  
  
    public static void Main () {
            int[] a = { -1, 4, -2, -5, 6, -8 };
  
    int n = a.Length;
  
    Console.Write(longestSubarray(a, n));
    }
}


PHP
= 0)
        {
            $ans = $mid;
            $e = $mid - 1;
        }
        else
        {
            $s = $mid + 1;
        }
    }
 
    return $ans;
}
 
// Function to return the
// longest subarray
function longestSubarray(&$a, $n)
{
    // Array for the suffix sum
    // of the above the array.
    $SuffixSum[$n] = 0;
 
    for ($i = $n - 1; $i >= 0; --$i)
    {
        $SuffixSum[$i] = $SuffixSum[$i + 1] +
                         $a[$i];
    }
 
    $ans = 0;
 
    // Search Space for potential
    // starting points of the subarray.
    // It will store the suffix sum
    // till i'th index in increasing order.
 
    // It will store the indexes
    // till which the suffix sum
    // is present in search space.
    $j = 0;
 
    for ($i = 0; $i < $n; ++$i)
    {
 
        // add the element to the search
        // space if the j=0 or if the
        // topmost element is lesser
        // than present suffix sum.
        if ($j == 0 or $SuffixSum[$i] >
                       $searchspace[$j - 1])
        {
            $searchspace[$j] = $SuffixSum[$i];
            $index[$j] = $i;
            $j++;
        }
 
        $idx = search($searchspace, 0, $j - 1,
                      $SuffixSum[$i + 1]);
 
        // Only when idx is not -1 an
        // subarray is possible with
        // ending index at i.
        if ($idx != -1)
            $ans = max($ans, $i -
                       $index[$idx] + 1);
    }
 
    return $ans;
}
 
// Driver Code
$a = array(-1, 4, -2, -5, 6, -8 );
$n = sizeof($a);
echo (longestSubarray($a, $n));
 
// This code is contributed
// by Shivi_Aggarwal
?>


Javascript


输出:
5

时间复杂度: O(N * log N)
辅助空间: O(N)