首页 > 其他分享 >LeetCode 918. 环形子数组的最大和

LeetCode 918. 环形子数组的最大和

时间:2023-09-25 17:06:40浏览次数:36  
标签:最大 nums int 环形 我们 vector 918 数组 LeetCode


环形子数组的最大和(medium)

题目链接:

918. 环形子数组的最大和

题目描述:

给定一个长度为 n环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和

环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i] 的下一个元素是 nums[(i + 1) % n]nums[i] 的前一个元素是 nums[(i - 1 + n) % n]

子数组 最多只能包含固定缓冲区 nums 中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], ..., nums[j] ,不存在 i <= k1, k2 <= j 其中 k1 % n == k2 % n

示例 1:

输入:nums = [1,-2,3,-2] 输出:3 解释:从子数组 [3] 得到最大和 3

示例 2:

输入:nums = [5,-3,5] 输出:10 解释:从子数组 [5,5] 得到最大和 5 + 5 = 10

示例 3:

输入:nums = [3,-2,2,-3] 输出:3 解释:从子数组 [3] 和 [3,-2,2] 都可以得到最大和 3

题目解析

这道题比较麻烦,我们给定的数组实际上是一个不连续的,但是我们的在逻辑上要求他们连续.也就是最后一个元素之后,接着就是我们第一个元素.这里面要求我们的需要进行处理.这道题也是要求我们的求连续子数组的最大连续和.

算法原理

状态表示

按照经验,我们以...为结尾表示状态.

dp[i]:表示以i位置为结尾,我们最大子数组最大的连续和.

这道题优点问题,我们不知道数组什么时候结束.但是我们求连续子数组的最大和无非就是下面的两个情况.

LeetCode 918. 环形子数组的最大和_动态规划

那么此时我我们发现两个关键点.

  • 对于情况1,我们求最大和就可以了
  • 对于情况2, 我们整个数组的和是确定,求最大和,那么我们求最小的和不就可以吗,然后一减

此时定义两个状态

  • f[i]: 表示以i位置,我们子数组的最大和
  • g[i]: 表示以i位置,我们子数组的最小和
状态转移方程

我们只谈g[i].这里我们想一下.对于我们的nums[i].这里我们可以有两个选择.

  • 选择nums[i]这一个元素作为我们的子数组 g[i]= nums[i]
  • 和i-1联合作为子数组. g[i] = dp[i-1]+nums[i]

那么这里我们求最小值g[i] = min(nums[i], g[i]+nums[i]);

初始化

仍旧只谈给g[i].这里添加一个辅助节点.那么对于满足g[1]=v[0],只需要g[0]=0就可以了.

填表顺序

从左向右填,两个一起填.

返回值

三个变量,一个记录最大和,一个记录总和,一个记录最小和.我们返回最大和以及总和减去最小和的较大值.

编写代码

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        if(nums.empty())
        return 0;
        int n = nums.size();
        vector<int> f(n+1, 0);
        vector<int> g(n+1, 0);
        int sum = 0;
        int maxNum =  INT_MIN;
        int minNum =  INT_MAX;
        for(int i = 1; i <= n; i++)
        {
            sum += nums[i-1];
            f[i] = std::max(f[i-1]+nums[i-1], nums[i-1]);
            maxNum = std::max(maxNum, f[i]);
            g[i] = std::min(g[i-1]+nums[i-1], nums[i-1]);
            minNum = std::min(minNum, g[i]);
        }
        return max(maxNum, sum - minNum);
    }
};


这里我们发现错误,我们分析一下,主要是总和以及较小和.我们发现他们相等.也就是差值为0,但是我们整个数组都是负数,不能出现这种情况,那么此时我们就要排除一些这个情况.

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        if(nums.empty())
        return 0;
        int n = nums.size();
        vector<int> f(n+1, 0);
        vector<int> g(n+1, 0);
        int sum = 0;
        int maxNum =  INT_MIN;
        int minNum =  INT_MAX;
        for(int i = 1; i <= n; i++)
        {
            sum += nums[i-1];
            f[i] = std::max(f[i-1]+nums[i-1], nums[i-1]);
            maxNum = std::max(maxNum, f[i]);
            g[i] = std::min(g[i-1]+nums[i-1], nums[i-1]);
            minNum = std::min(minNum, g[i]);
        }
        if((sum - minNum) == 0)
        return maxNum;

        return max(maxNum, sum - minNum);
    }
};

LeetCode 918. 环形子数组的最大和_子数组_02

标签:最大,nums,int,环形,我们,vector,918,数组,LeetCode
From: https://blog.51cto.com/byte/7597239

相关文章

  • LeetCode 53. 最大子数组和
    最大子数组和(medium)题目链接:53.最大子数组和题目描述:给你一个整数数组nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。示例1:输入:nums=[-2,1,-3,4,-1,2,1,-5,4]输出:6解释:连续子数组[4,-1,2,1]的和最大......
  • leetcode21. 合并两个有序链表
    合并两个有序链表题目链接21.合并两个有序链表将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输出:[0......
  • [LeetCode] 1353. Maximum Number of Events That Can Be Attended 最多可以参加的会
    Youaregivenanarrayof events where events[i]=[startDayi,endDayi].Everyevent i startsat startDayi andendsat endDayi.Youcanattendanevent i atanyday d where startTimei<=d<=endTimei.Youcanonlyattendoneeventatanytime ......
  • 两两交换链表中的节点、删除链表倒数第N个结点、链表相交、环形链表
    题目要求LeetCode24两两交换链表中的节点LeetCode19删除链表的倒数第N个结点LeetCode面试题02.07链表相交LeetCode142环形链表II题目思路24两两交换链表中的节点  本题采用具有虚拟头结点的链表来写,卡哥的示意图如下:  首先要交换的两个链表的前一个结点,然后修改指......
  • #yyds干货盘点# LeetCode程序员面试金典:除自身以外数组的乘积
    题目:给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在  32位 整数范围内。请 不要使用除法,且在 O(n) 时间复杂度内完成此题。 示......
  • #yyds干货盘点# LeetCode程序员面试金典:全 O(1) 的数据结构
    1.简述:请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。实现 AllOne 类:AllOne() 初始化数据结构的对象。inc(Stringkey) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。dec(Stringkey) 字符串 k......
  • Hugging News #0918: Hub 加入分类整理功能、科普文本生成中的流式传输
    每一周,我们的同事都会向社区的成员们发布一些关于HuggingFace相关的更新,包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等,我们将其称之为「HuggingNews」。本期HuggingNews有哪些有趣的消息,快来看看吧!......
  • 算法训练day18 LeetCode 513
    算法训练day18LeetCode513.112.106513.找树左下角的值题目513.找树左下角的值-力扣(LeetCode)题解代码随想录(programmercarl.com)递归方式单独数据存储最大深度,和此深度的结点值递归后要注意回溯classSolution{public:intmaxDepth=INT_MIN;......
  • Leetcode刷题21.合并两个有序链表
    将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输出:[0] 提示:两个链表的节点数目......
  • 算法训练day8 LeetCode 344
    算法训练day8:LeetCode344.541.151.剑指offer05.58.344.反转字符串题目344.反转字符串-力扣(LeetCode)题解代码随想录(programmercarl.com)classSolution{public:voidreverseString(vector<char>&s){for(inti=0,j=s.size()-1;i......