算法日常・每日刷题--<动态规划>20

918. 环形子数组的最大和 - 力扣(LeetCode)

题目描述

给定一个长度为 n 的环形整数数组 nums,环形数组意味着数组的末端将会与开头相连呈环状。找出这个环形数组的非空连续子数组的最大和。

子数组:必须是连续的,环形代表子数组可以跨数组首尾,例如数组 [5,-3,5],可以选取 [5,5](第一个 5 和最后一个 5)。

核心思路

环形子数组最大和只有两种情况:

  1. 不跨首尾 :普通最大子数组和(就是 LeetCode53 最大子序和),记为ret1
  2. 跨首尾 :子数组包含数组头部 + 尾部,等价于总和减去中间一段最小子数组和 ,sum - ret2,ret2是最小子数组和

⚠️ 边界特例:数组全部都是负数 此时总和减去最小子数组,会得到空数组(不合法,题目要求子数组非空),这种情况直接返回普通最大子数组(也就是数组里最大的单个负数)。

状态定义

  • fx[i]:以i下标结尾的最大子数组和
  • gx[i]:以i下标结尾的最小子数组和

状态转移:

遍历过程中:

  • ret1:记录全局最大子数组和
  • ret2:记录全局最小子数组和
  • sum:整个数组总和
  • flag:标记数组是否存在正数,用来判断是否全负
cpp 复制代码
class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        int n=nums.size();
        vector<int>fx(n,0);
        auto gx=fx;
        fx[0]=nums[0];
        gx[0]=nums[0];
        int ret1=nums[0];
        int ret2=nums[0];
        int sum=nums[0];
        int flag=0;
        for(int i=1;i<n;i++)
        {
            fx[i]=max(fx[i-1]+nums[i],nums[i]);
            gx[i]=min(gx[i-1]+nums[i],nums[i]);
            ret1=ret1>fx[i]?ret1:fx[i];
            ret2=ret2<gx[i]?ret2:gx[i];
            sum+=nums[i];
            if(nums[i]>0)
            flag=1;
        }
        if(flag==0)
        return ret1;
        return max(ret1,sum-ret2);
    }
};
相关推荐
郝学胜-神的一滴1 小时前
游戏设计:原型与开发 19:U3D工位布置与性格说明书
人工智能·算法·unity·unreal engine·游戏策划·游戏设计
hahaha60162 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
文丑颜不良啊2 小时前
LeetCode1541~1560题目解析
java·leetcode
YSL0701242 小时前
一文通关-----树和二叉树
数据结构·算法
青少儿编程课堂2 小时前
蓝桥杯青少组图形化+信息素养+电子学会Scratch考级:校园口算闯关解析
c++·python·算法·bfs·信息学竞赛
computersciencer2 小时前
应用贝叶斯公式:迟到了,那坐的是哪种交通工具呢?
算法·机器学习·概率论
若亦_2 小时前
排序>>交换排序
java·数据结构·算法
dialect_11 小时前
KMP算法
开发语言·c++·算法
reikocao11 小时前
卡尔曼滤波的动态机制:P如何改变融合权重
算法
漂流瓶jz12 小时前
UVA-1612 猜名次 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·题解·排序·aoapc·算法竞赛入门经典