最大连续子数组和,最大连续子数组乘积

本文介绍了如何使用动态规划解决最大连续子数组和问题,以及如何处理最大连续子数组乘积的特殊情况,包括更新最大值、最小值和最终答案的过程。通过实例代码展示了算法的核心思路和优化技巧。
  1. 最大连续子数组和

动态规划的是首先对数组进行遍历,当前最大连续子序列和为 sum,结果为 ans
如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字
如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字
每次比较 sum 和 ans的大小,将最大值置为ans,遍历结束返回结果

维护两个变量,在动态规划过程中,一个是tmp_sum即降维了的dp数组dp[i], 一个是最终答案ans。

每个i都要记得更新一次ans,因为最大连续子数组和不一定发生在最终状态。

时间复杂度:O(n)
空间复杂度:O(1)

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        tmp_sum = 0
        res = nums[0]
        for num in nums:
            tmp_sum = max(tmp_sum + num, num)
            res = max(res, tmp_sum)
        return res


  1. 最大连续子数组乘积
    在这里插入图片描述
    我们需要维护目前为止的最大值,最小值,和最终的ans。

因为最大值可能因为*当前元素为负数就变成最小值。
为什么更新Max和Min要带上nums[i]?因为如果nums[i] == 0, 那么Max,Min都会成0,然后下一轮从max[i+1] = max(nums[i+1], max[i+1], min[i+1]) = nums[i+1] 重新开始。
每个i都要记得更新一次ans,因为最大连续子数组乘积不一定发生在最终状态。

class Solution:
    # @param {integer[]} nums
    # @return {integer}
    def maxProduct(self, nums):
        # 将currentMax, currentMin, ans都初始化为第一个数组元素
        currentMax, currentMin, ans = nums[0], nums[0], nums[0]
        for i in range(1, len(nums)):
            n = nums[i]
            # 事先保存currentMax[i-1]
            tmp = currentMax 
            # 更新currentMax[i-1] to currentMax[i]
            currentMax = max(n, n*currentMax, n*currentMin)
            # 更新currentMax[i-1] to currentMax[i]
            currentMin = min(n, n*tmp, n*currentMin)
            # 更新 ans
            ans = max(ans, currentMax)
        return ans

代码摘自leetcode对应题目题解。

### 最大连续子数组乘积的C语言实现 为了实现最大连续子数组乘积问题,可以采用动态规划的思想。以下是基于引用内容专业知识设计的一个完整的解决方案。 #### 动态规划的核心思想 由于存在负数的情况,在计算过程中不仅需要维护当前的最大值,还需要维护当前的最小值。这是因为当遇到负数时,之前的小值可能通过相乘变为较大的正值[^2]。 定义两个辅助变量 `max_product` `min_product` 来分别记录到当前位置为止的最大乘积最小乘积。对于每一个新元素,更新这两个变量并同步跟踪全局最大值。 --- #### C语言代码实现 以下是一个高效的 O(n) 时间复杂度的 C 语言实现: ```c #include <stdio.h> #include <limits.h> int maxProduct(int* nums, int numsSize){ if (numsSize == 0) return 0; // 初始化三个变量:当前最大值、当前最小值以及最终结果 int current_max = nums[0]; int current_min = nums[0]; int result = nums[0]; for (int i = 1; i < numsSize; ++i) { // 如果当前数字为负,则交换最大最小值 if (nums[i] < 0) { int temp = current_max; current_max = current_min; current_min = temp; } // 更新当前最大最小值 current_max = (current_max * nums[i]) > nums[i] ? (current_max * nums[i]) : nums[i]; current_min = (current_min * nums[i]) < nums[i] ? (current_min * nums[i]) : nums[i]; // 更新全局最大值 result = (result > current_max) ? result : current_max; } return result; } // 测试函数 void testMaxProduct() { int nums[] = {-2, 3, -4}; int size = sizeof(nums)/sizeof(nums[0]); printf("Maximum Product Subarray: %d\n", maxProduct(nums, size)); } int main(){ testMaxProduct(); return 0; } ``` --- #### 关键点解析 1. **初始化** 初始状态设置为第一个元素,即 `current_max`, `current_min`, `result` 都等于 `nums[0]`。 2. **处理负数情况** 当前元素如果是负数,那么之前的最小值可能会变成新的最大值,因此需要交换 `current_max` `current_min` 的角色。 3. **动态转移方程** 对于每个位置 \(i\), \[ \text{current\_max} = \max(\text{nums}[i], \text{current\_max} \times \text{nums}[i], \text{current\_min} \times \text{nums}[i]) \] 同理, \[ \text{current\_min} = \min(\text{nums}[i], \text{current\_max} \times \text{nums}[i], \text{current\_min} \times \text{nums}[i]) \] 4. **优化空间复杂度** 只需常量级别的额外空间即可完成上述操作,无需开辟额外数组存储中间结果。 --- #### 复杂度分析 - **时间复杂度**: \(O(n)\),只需一次遍历整个数组。 - **空间复杂度**: \(O(1)\),仅使用固定数量的变量来保存临时数据。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值