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

918. 环形子数组的最大和 (Medium)

时间:2023-07-22 16:12:25浏览次数:52  
标签:Medium nums int sum min 环形 918 数组 dp

问题描述

918. 环形子数组的最大和 (Medium)

给定一个长度为 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

提示:

  • n == nums.length
  • 1 <= n <= 3 * 10⁴
  • -3 * 10⁴ <= nums[i] <= 3 * 10⁴

解题思路

我们令 $dp[i]$ 表示以 $nums[i]$ 结尾的子数组的最大和,那么我们分两种情况讨论即可:

  • 子数组是连续的一段,即 $tail >= head$;
  • 子数组被分成了两段,即 $tail < head$;

代码

class Solution {
  public:
    int maxSubarraySumCircular(vector<int> &nums) {
        int n = nums.size();
        if (n == 1) {
            return nums[0];
        }
        vector<int> dp(n, INT_MIN);
        // 先求 dp[0];
        // 分情况讨论,先统计正常的情况,再统计被分成两段的情况
        int sum = accumulate(nums.begin(), nums.end(), 0);
        vector<int> normal(n, INT_MIN);
        dp[0] = nums[0];
        for (int i = 1; i < n; ++i) {
            dp[i] = max(nums[i], nums[i] + dp[i - 1]);
        }
        // 寻找以 head 为起点的最小值
        vector<int> min_sum(n, 0);
        min_sum[n - 1] = nums[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            min_sum[i] = min(min_sum[i + 1] + nums[i], nums[i]);
        }
        int res = INT_MIN;
        for (int i = 0; i < n - 1; ++i) {
            dp[i] = max(dp[i], sum - min_sum[i + 1]);
            res = max(res, dp[i]);
        }
        return max(res, dp[n - 1]);
    }
};

标签:Medium,nums,int,sum,min,环形,918,数组,dp
From: https://www.cnblogs.com/zwyyy456/p/17573529.html

相关文章

  • 2023.7.20 环形子数组的最大和
    求子数组最大和可以用dp解决,所以环形子数组也可以用dp解决。最简单的就是破环成链,将原数组再复制一遍然后接到尾端,然后对每个起点做一次求子数组最大和dp。但是由于n的范围较大,这样做的时间复杂度是\(n^2\),会超时。所以必须想办法优化。根据这张图,我们可以把子数组分为二种情......
  • 950. Reveal Cards In Increasing Order (Medium)
    Description950.RevealCardsInIncreasingOrder(Medium)Youaregivenanintegerarraydeck.Thereisadeckofcardswhereeverycardhasauniqueinteger.Theintegerontheithcardisdeck[i].Youcanorderthedeckinanyorderyouwant.Initially......
  • 950. 按递增顺序显示卡牌 (Medium)
    问题描述950.按递增顺序显示卡牌(Medium)牌组中的每张卡牌都对应有一个唯一的整数。你可以按你想要的顺序对这套卡片进行排序。最初,这些卡牌在牌组里是正面朝下的(即,未显示状态)。现在,重复执行以下步骤,直到显示所有卡牌为止:从牌组顶部抽一张牌,显示它,然后将其从牌组中移出。......
  • [Typescript] 149 Medium - Triangular number
    GivenanumberN,findtheNthtriangularnumber,i.e. 1+2+3+...+N/*_____________YourCodeHere_____________*/exporttypeNumberToArray<Textendsnumber,Rextends1[]=[]>=R["length"]extendsT?R:NumberToArray&......
  • [Typescript Challenge] 148 Medium - CartesianProduct
    Given2sets(unions),returnitsCartesianproductinasetoftuples,e.g.CartesianProduct<1|2,'a'|'b'>//[1,'a']|[2,'a']|[1,'b']|[2,'b'] Solution:/*____________......
  • c++环形队列的简单实现
    环形队列可以通过维护count来间接维护tail和head指针的关系,简化程序,避免了直接使用tail和head指针,读写时head与tail回环时的比较处理,判断队列元素长度时的复杂处理,如下为不基于count而是直接使用head和tail指针比较的环形队列的实现,逻辑较为复杂uint32_tCAudioRingBuffer::Da......
  • 直播app源码,canvas 环形刻度 进度条
    直播app源码,canvas环形刻度进度条 letctx=nullletobj={}Page({ data:{ }, onLoad:function(options){},   onReady(){  this.animation() }, animation(){  constquery=wx.createSelectorQuery()  query.select('#firstCanvas') ......
  • LeetCode -- 918. 环形子数组的最大和
     遇到环形问题一般有两种考虑方法:1.破环成链2.分为数组中间部分和数组两边部分分别考虑本题采用第二种考虑方法,将原数组分为中间部分和两边部分分别考虑。中间部分即为子数组最大和,两边部分计总和减去中间部分最小和。classSolution{public:intma......
  • LeetCode 142. 环形链表 II
    /***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode(intx):val(x),next(NULL){}*};*/classSolution{public:ListNode*detectCycle(ListNode*head){if(!head)return......
  • 【雕爷学编程】Arduino动手做(124)---24位WS2812环形灯板
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......