C++程序 寻找最大积子数组

C++程序 寻找最大积子数组

给定一个包含正数和负数的数组,找到最大积子数组的积。预期时间复杂度为O(n),只能使用O(1)的额外空间。

示例:

输入:arr[]={6, -3, -10, 0, 2}
输出:180 //最大子数组分别为{6, -3, -10}

输入:arr[]={-1, -3, -10, 0, 60}
输出:60 //最大子数组分别为{60}

输入:arr[]={-2, -40, 0, -2, -3}
输出:80 //最大子数组分别为{-2, -40}

Naive解法:

思想是遍历每个连续的子数组,找到每个子数组的积,并从这些结果中返回最大积。

下面是上述方法的实现。

// C++ program to find Maximum Product Subarray
#include <bits/stdc++.h>
using namespace std;
 
/* 返回最大积子数组的积。*/
int maxSubarrayProduct(int arr[], int n)
{
    // 初始化结果
    int result = arr[0];
 
    for (int i = 0; i < n; i++)
    {
        int mul = arr[i];
        // 遍历当前子数组
        for (int j = i + 1; j < n; j++)
        {
            // 每次更新结果
            // 以便监视最大积
            result = max(result, mul);
            mul *= arr[j];
        }
        // 更新最后一个元素的结果。
        result = max(result, mul);
    }
    return result;
}
 
// 主函数
int main()
{
    int arr[] = { 1, -2, -3, 0, 7, -8, -2 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "最大子数组积是:"
         << maxSubarrayProduct(arr, n);
    return 0;
}
 
// 由yashbeersingh42提供的代码```  

输出结果:

最大子数组积是:112

时间复杂度: O(N 2 )

辅助空间: O(1)

高效解法:

以下解法假设给定的输入数组总有一个正的输出。该解法适用于上述所有情况。但不适用于数组,例如 {0, 0, -20, 0}、{0,0,0} 等。该解决方案可以很容易地修改以处理此问题。
它类似于最大总和连续子数组问题。这里唯一需要注意的是,最大积也可以通过前一个元素的最小(负)积乘以此元素获得。例如,在数组 {12, 2, -3, -5, -6, -2} 中,当我们位于元素 -2 时,最大积是最小积,它以 -6 结尾并乘以 -2。

// C++ 程序,用于查找最大乘积子数组
#include <bits/stdc++.h>
using namespace std;
 
/* 返回最大乘积子数组的乘积。
假设给定的数组总是有一个乘积大于1的子数组 */
int maxSubarrayProduct(int arr[], int n)
{
    // 最大正结束位置的乘积
    int max_ending_here = 1;
 
    // 最小负结束位置的乘积
    int min_ending_here = 1;
 
    // 初始化总体最大产品
    int max_so_far = 0;
    int flag = 0;
    /* 遍历数组。
    i次迭代后,保留以下值:
    max_ending_here始终为1,或以arr[i]结尾的一些正数乘积
    min_ending_here始终为1,或以arr[i]结尾的某些负数乘积 */
    for (int i = 0; i < n; i++)
    {
        /* 如果这个元素是正数,请更新max_ending_here。仅在min_ending_here为负数时更新min_ending_here */
        if (arr[i] > 0)
        {
            max_ending_here = max_ending_here * arr[i];
            min_ending_here
                = min(min_ending_here * arr[i], 1);
            flag = 1;
        }
 
        /* 如果这个元素是0,则最大乘积无法在这里结束,请将max_ending_here和min_ending_here都设置为0。
        假设:输出始终大于或等于1。 */
        else if (arr[i] == 0) {
            max_ending_here = 1;
            min_ending_here = 1;
        }
 
        /* 如果这个元素是负数。 这是棘手的,可以使max_ending_here为1或正数。
         min_ending_here可以为1或负数。
         next max_ending_here将始终是prev。
         min_ending_here * arr[i],如果prev max_ending_here为1,则next min_ending_here为1,否则
         next min_ending_here将是prev max_ending_here * arr[i] */
 
        else {
            int temp = max_ending_here;
            max_ending_here
                = max(min_ending_here * arr[i], 1);
            min_ending_here = temp * arr[i];
        }
 
        // 如果需要,则更新max_so_far
        if (max_so_far < max_ending_here)
            max_so_far = max_ending_here;
    }
    if (flag == 0 && max_so_far == 0)
        return 0;
    return max_so_far;
}
 
// 驱动器代码
int main()
{
    int arr[] = { 1, -2, -3, 0, 7, -8, -2 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "最大子数组乘积是 "
         << maxSubarrayProduct(arr, n);
    return 0;
}
 
// 本代码由rathbhupendra捐赠```  

输出

最大子数组乘积是 112

时间复杂度: O(n)

辅助空间: O(1)

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

C++ 示例