首页 > 其他分享 >【动态规划】力扣918. 环形子数组的最大和

【动态规划】力扣918. 环形子数组的最大和

时间:2024-08-05 15:24:39浏览次数:11  
标签:leftMax 数组 nums int 复杂度 环形 力扣 918 resMax

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

在这里插入图片描述

动态规划

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        int n = nums.size();
        vector<int> leftMax(n);
        int pre = nums[0], res = nums[0], leftSum = nums[0] ;
        leftMax[0] = nums[0];
        for(int i = 1; i < n; i++){
            pre = max(nums[i], pre + nums[i]);
            res = max(res, pre);
            leftSum += nums[i];
            leftMax[i] = max(leftMax[i-1], leftSum);
        }

        int rightSum = 0;
        for(int i = n - 1; i > 0 ; i--){
            rightSum += nums[i];
            res = max(res, rightSum + leftMax[i-1]);
        }
        return res;
    }
};

时间复杂度:O(n),其中 n 是 nums 的长度。求解第一种情况的时间复杂度为 O(n),求解 leftMax 数组和枚举后缀的时间复杂度为 O(n),因此总的时间复杂度为 O(n)。

空间复杂度:O(n),其中 n 是 nums 的长度。过程中我们使用 leftMax 来存放最大前缀和。

用动态规划的思路来讲,是要列出可能的情况。在这道题中一种情况是不跨越尾部,也就是正常的子段,另外一种是跨越尾部。针对特殊的跨越尾部的情况,使用leftMax来记录第 i 个元素之前的最大子段和,然后从右到左遍历数组,最后比较两种情况的最大值即可。

取反

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        int n = nums.size();
        int sum = nums[0];
        int preMax = nums[0], resMax = nums[0];
        int preMin = nums[0], resMin = nums[0];
        for(int i = 1; i < n; i++){
            preMax = max(nums[i], preMax + nums[i]);
            resMax = max(resMax, preMax);
            preMin = min(nums[i], preMin + nums[i]);
            resMin = min(resMin, preMin);
            sum += nums[i];
        }

        if(resMax < 0){
            return resMax;
        }
        else{
            return max(resMax, sum - resMin);
        }
    }
};

时间复杂度:O(n),其中 n 是 nums 的长度。
空间复杂度:O(1)。过程中只是用到了常数个变量。

这是一个更加巧妙的思路,并且有更低的空间复杂度。他的思想是所有数组元素之和减去中间的一段最小子段和,剩下的部分就是最大的经过头尾的子段和,再与正常子段和比较即可。要注意的是,当resMax < 0 的时候,sum - resMin返回的是一个空数组,这时候只要返回resMax。

标签:leftMax,数组,nums,int,复杂度,环形,力扣,918,resMax
From: https://blog.csdn.net/sjsjs11/article/details/140918156

相关文章

  • Echarts 实现圆角环形图
     第一种方式:使用bar实现想要的效果:代码实现:constchartData={title:{text:'97',//圆环中间数字textStyle:{color:'#222222',fontSize:20,},subtext:'成功数',subtextS......
  • 134. 加油站【 力扣(LeetCode) 】
    一、题目描述  在一条环路上有n个加油站,其中第i个加油站有汽油gas[i]升。  你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油站需要消耗汽油cost[i]升。你从其中的一个加油站出发,开始时油箱为空。  给定两个整数数组gas和cost,如果你可以......
  • 135. 分发糖果【 力扣(LeetCode) 】
    一、题目描述  n个孩子站成一排。给你一个整数数组ratings表示每个孩子的评分。  你需要按照以下要求,给这些孩子分发糖果:每个孩子至少分配到1个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。  请你给每个孩子分发糖果,计算并返回需要准备的最少糖果数......
  • 算法力扣刷题记录 六十四【216.组合总和III】
    前言回溯第二篇。回顾:上一篇学了回溯的基础知识和模版;组合练习题一应用了一次模版。本文继续组合问题练习:记录六十四【216.组合总和III】。一、题目阅读找出所有相加之和为n的k个数的组合,且满足下列条件:只使用数字1到9每个数字最多使用一次返回所有可能的有效......
  • 算法力扣刷题总结篇 ——【五】二叉树章节
    前言从记录三十五【二叉树基础和递归遍历】到记录六十二【538.把二叉搜索树转换为累加树】28篇文章都是二叉树的章节。所以总结的任务量有点大啊。但还是要做的。完成之后,开启新章节……继续。一、题目回顾1-5:遍历方式模版题。6-14:确定遍历顺序。后序居多——先统......
  • 【每日一题】【并查集】【力扣】695.岛屿的最大面积 C++
    力扣695.岛屿的最大面积695.岛屿的最大面积题目描述给你一个大小为m×nm\timesnm×n的二进制矩阵......
  • 141.环形链表
    给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。注意:pos 不作为参数进行传递 。仅仅是为......
  • 新手力扣刷题——很懵?看不懂开头?
    最近在B站上看到,很多大佬都推荐在力扣网站上刷题,本苟蒻也是心血来潮也注册了一个账号,想开启自己的刷题之路,结果一看界面一下给我看懵了这是什么开头啊?为什么没有头文件?其实完全不用担心,更不要有放弃的想法,如果你跟我一样只学过C,你可以把它当成一个自定义函数,一些什么头文......
  • 力扣-6-Z 字形变换
    其实叫“N字形变换”更形象第一版代码,在二维数组中模拟打印过程,但是时间和空间效率都很差,都是n2stringconvert(strings,intnumRows){ intlen=s.size(); //如果只有一行或者只有一列则直接输出 if(numRows==1||numRows>=len)returns; //计算每个周期占......
  • 力扣--59.螺旋矩阵II
      模拟顺时针画矩阵的过程:填充上行从左到右填充右列从上到下填充下行从右到左填充左列从下到上由外向内一圈一圈这么画下去/***生成一个包含从1到n*n的数字的矩阵*@param{number}n-矩阵的大小,为正整数*@return{number[][]}-返回一个nxn的二维数......