首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

过于真实!三餐不定,只为四季研发,拼得五脏俱损 | 每日趣闻

  • 24-03-05 03:04
  • 4147
  • 5932
blog.csdn.net

640?wx_fmt=gif

640?wx_fmt=jpeg

对此,你是怎么看的呢?

“每日趣闻”是程序人生的新栏目,与你分享一些关于程序员、关于IT行业的趣事,你喜欢这样的形式吗?

百度大脑AI硬件面世、微软AI实验室进军AI产业,带来了那些契机?

https://edu.csdn.net/topic/ai30?utm_source=cxrs_bw

 

640?wx_fmt=png

 

640?wx_fmt=jpeg

 

 
 

640?wx_fmt=gif点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

640?wx_fmt=png你点的每个“在看”,我都认真当成了喜欢

程序人生
微信公众号
笑谈开发轶事,品味程序人生。

题解:环形数组的最大子数组和


问题描述

我们需要找到一个环形数组的最大子数组和,即找到一段连续的子数组(可能跨越数组的首尾连接)使得其和最大。


解决思路

环形数组的最大子数组和问题,可以分为两种情况讨论:

  1. 子数组没有跨越数组的首尾(普通子数组)。

    • 这种情况下,问题退化为经典的 最大子数组和 问题,可以用 Kadane 算法 高效解决。
  2. 子数组跨越了数组的首尾。

    • 这种情况下,最大子数组和可以表示为: [ \text{totalSum} - \text{minSubarraySum} ]
      • totalSum 是数组的总和。
      • minSubarraySum 是子数组的最小和。

因此,我们需要分别计算:

  • 普通的最大子数组和(Kadane 算法)。
  • 数组的总和。
  • 最小子数组和(Kadane 算法的变体)。

最后,结果为以下两者的最大值: [ \text{result} = \max(\text{maxSubarraySum}, \text{totalSum} - \text{minSubarraySum}) ]


特殊情况

如果数组中所有元素都为负数,跨越首尾的子数组和将等于 (\text{totalSum} - \text{minSubarraySum} = 0),这不合法。此时应直接返回普通的最大子数组和。


算法步骤

  1. 使用 Kadane 算法求解普通的最大子数组和(maxSubarraySum)。
  2. 计算数组的总和(totalSum)。
  3. 使用 Kadane 算法求解最小子数组和(minSubarraySum)。
  4. 如果 totalSum == minSubarraySum(所有元素为负数),直接返回 maxSubarraySum。
  5. 否则返回: [ \max(\text{maxSubarraySum}, \text{totalSum} - \text{minSubarraySum}) ]

代码实现

cpp
代码解读
复制代码
#include #include #include // 使用 Kadane 算法计算最大或最小子数组和 int kadane(const std::vector<int>& nums, bool findMax) { int current = nums[0], best = nums[0]; for (size_t i = 1; i < nums.size(); ++i) { if (findMax) { current = std::max(nums[i], current + nums[i]); best = std::max(best, current); } else { current = std::min(nums[i], current + nums[i]); best = std::min(best, current); } } return best; } // 主函数:环形数组的最大子数组和 int solution(std::vector<int>& nums) { int n = nums.size(); // Case 1: 最大子数组和(不考虑环形) int maxSubarraySum = kadane(nums, true); // Case 2: 数组的总和 int totalSum = 0; for (int num : nums) { totalSum += num; } // Case 3: 最小子数组和 int minSubarraySum = kadane(nums, false); // Case 4: 判断是否需要考虑环形情况 if (totalSum == minSubarraySum) { // 如果总和等于最小子数组和,说明所有元素为负数,只能返回 maxSubarraySum return maxSubarraySum; } else { // 否则,返回普通最大子数组和或环形最大子数组和中的较大值 return std::max(maxSubarraySum, totalSum - minSubarraySum); } } // 测试用例 int main() { std::vector<int> nums1 = {-1, -2, 3, -2}; std::vector<int> nums2 = {-5, -3, 5}; std::vector<int> nums3 = {-3, -1, 2, -1}; std::vector<int> nums4 = {-2, -3, -1}; std::cout << (solution(nums1) == 3) << std::endl; // 输出:3 std::cout << (solution(nums2) == 5) << std::endl; // 输出:5 std::cout << (solution(nums3) == 2) << std::endl; // 输出:2 std::cout << (solution(nums4) == -1) << std::endl; // 输出:-1 return 0; }

代码解析

  1. Kadane 算法

    • 用于求解最大或最小子数组和。
    • 时间复杂度为 (O(n))。
  2. 特殊处理

    • 当数组中所有元素均为负数时,totalSum == minSubarraySum,无法通过环形方式求解。这时直接返回 maxSubarraySum。
  3. 结果计算

    • 普通最大子数组和 maxSubarraySum。
    • 环形最大子数组和 totalSum - minSubarraySum。
    • 返回两者的较大值。

复杂度分析

  1. 时间复杂度

    • Kadane 算法求解最大和最小子数组各需 (O(n))。
    • 计算总和需要 (O(n))。
    • 总时间复杂度:(O(n))。
  2. 空间复杂度

    • 使用常数额外空间。
    • 总空间复杂度:(O(1))。

测试分析

示例 1

输入:nums = [-1, -2, 3, -2]

  • maxSubarraySum = 3(子数组为 [3])。
  • totalSum = -2。
  • minSubarraySum = -4(子数组为 [-1, -2])。
  • totalSum - minSubarraySum = 2。
  • 输出:max(3, 2) = 3。

示例 2

输入:nums = [-5, -3, 5]

  • maxSubarraySum = 5。
  • totalSum = -3。
  • minSubarraySum = -8。
  • totalSum - minSubarraySum = 5。
  • 输出:max(5, 5) = 5。

示例 3

输入:nums = [-3, -1, 2, -1]

  • maxSubarraySum = 2。
  • totalSum = -3。
  • minSubarraySum = -5。
  • totalSum - minSubarraySum = 2。
  • 输出:max(2, 2) = 2。

示例 4

输入:nums = [-2, -3, -1]

  • maxSubarraySum = -1。
  • totalSum = -6。
  • minSubarraySum = -6。
  • totalSum == minSubarraySum,返回 `maxSubarraySum =

-1。


总结

  1. 问题拆解

    • 普通子数组和问题使用 Kadane 算法解决。
    • 环形子数组和问题通过 totalSum - minSubarraySum 转化。
  2. 关键点

    • 需要处理特殊情况:所有元素为负数时,只能返回普通的最大子数组和。
  3. 算法效率

    • 时间复杂度 (O(n)) 和空间复杂度 (O(1)) 确保算法能够高效处理大规模数组。
  4. 代码优势

    • 简洁明了,易于扩展。
    • 通过分情况处理,覆盖所有可能的输入场景。

此方法是一种优化的、通用的解决方案,可以很好地解决环形数组的最大子数组和问题。

注:本文转载自blog.csdn.net的CSDN 程序人生的文章"https://blog.csdn.net/csdnsevenn/article/details/89368862"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top