当前位置: 首页 > news >正文

力扣 1856. 子数组最小乘积的最大值

题目来源:https://leetcode.cn/problems/maximum-subarray-min-product/

大致题意:
给一个只包含正数的数组,求所有子数组的最小值与子数组和乘积的最大值


思路

根据题意,首先需要求子数组的最小值与子数组和乘积,才能在所有乘积中找到最大值

要想求出子数组的最小值与子数组和乘积,需要先确定子数组的最小值

而要确定子数组的最小值,需要先确定子数组的内容,简单的方法是直接枚举所有子数组,然后确定最小值,但是这样的时间复杂度为 O(n2)。还有一种逆向思维的方法

  • 即确定以数组每个元素为最小值的子数组左右边界 l 和 r,可以通过单调栈求出边界
  • 也就是确定以 nums[i] 为最小值的子数组左右边界,那么可知,在边界内包含 nums[i] 的所有子数组的最小值都为 nums[i],而这些子数组与 nums[i] 的最大乘积即为 l ~ r 的所有元素和与 nums[i] 的乘积(因为数组所有元素都为正数)

于是就确定了子数组的最小值与子数组和乘积,然后可以通过枚举每个元素作为最小值的子数组与对应子数组和的乘积求出所有子数组的最小值与子数组和乘积的最大值

在解题时,可以通过前缀和来确定给定范围的子数组和

具体的解题思路为

  1. 使用单调栈求出每个元素作为最小值的子数组的左右边界
  2. 统计前缀和
  3. 根据左边界和前缀和获取对应的子数组和,子数组和与当前元素的乘积即为当前元素为最小值的子数组的最小值与子数组和乘积的最大值。于是,统计最大值(此最大值表示当前元素作为最小值的所有子数组中子数组的最小值与子数组和乘积的最大值)中的最大值(该最大值即为所有子数组的最小值与子数组和乘积的最大值),即为答案

代码:

public int maxSumMinProduct(int[] nums) {
        int n = nums.length;
        // 每个元素作为最小值的子数组左边界
        int[] left = new int[n];
        // 每个元素作为最小值的子数组右边界
        int[] right = new int[n];
        // 单调栈
        Deque<Integer> stack = new ArrayDeque<>();
        // 获取左边界
        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && nums[stack.peek()] >= nums[i]) {
                stack.pop();
            }
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }
        stack.clear();
        // 获取右边界
        for (int i = n - 1; i >= 0; i--) {
            while (!stack.isEmpty() && nums[stack.peek()] > nums[i]) {
                stack.pop();
            }
            right[i] = stack.isEmpty() ? n : stack.peek();
            stack.push(i);
        }
        long ans = 0;
        // 前缀和
        long[] preSum = new long[n];
        preSum[0] = nums[0];
        // 统计前缀和
        for (int i = 1; i < n; i++) {
            preSum[i] = preSum[i - 1] + nums[i];
        }
        // 统计最大值
        for (int i = 0; i < n; i++) {
            // cur 即为当前元素作为最小值的子数组和的最大值
            long cur = preSum[right[i] - 1];
            if (left[i] != -1) {
                cur -= preSum[left[i]];
            }
            // cur * nums[i] 即为 当前元素为最小值 的 【子数组的最小值与子数组和乘积】 的 最大值
            ans = Math.max(cur * nums[i], ans);
        }
        ans %= 1000000007;
        return (int) ans;
    }

相关文章:

  • Qt实现控件的折叠收起和展开的功能
  • #传输# #传输数据判断#
  • 腾讯高工用 4 部分就讲清楚了 Spring 全家桶 + 微服务
  • Linux(WSL)安装CUDA
  • Oracle VM VirtualBox Ubuntu设置共享文件夹
  • 【机器学习】DBSCAN聚类算法的理论/实现与调参
  • 32、Java——迷你图书管理器(对象+JDBC)
  • pycharm联合Anaconda
  • 不知道视频怎么转音频?手把手教你视频转音频
  • 【C++笔试强训】第十五天
  • 应用软件漏洞排名
  • 基于YOLOV7的桥梁基建裂缝检测
  • BH1750 传感器实战教学 —— 驱动移植篇
  • 考研数学——张宇八套卷
  • ARM 汇编基础
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • JavaScript-如何实现克隆(clone)函数
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 0x05 Python数据分析,Anaconda八斩刀
  • CSS实用技巧干货
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • emacs初体验
  • Hibernate【inverse和cascade属性】知识要点
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Java 最常见的 200+ 面试题:面试必备
  • javascript面向对象之创建对象
  • java中的hashCode
  • JDK 6和JDK 7中的substring()方法
  • node和express搭建代理服务器(源码)
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Redis中的lru算法实现
  • Spring Cloud Feign的两种使用姿势
  • springboot_database项目介绍
  • 多线程 start 和 run 方法到底有什么区别?
  • 关于Flux,Vuex,Redux的思考
  • 技术发展面试
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 将 Measurements 和 Units 应用到物理学
  • 前嗅ForeSpider中数据浏览界面介绍
  • 实现简单的正则表达式引擎
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 微信公众号开发小记——5.python微信红包
  • 昨天1024程序员节,我故意写了个死循环~
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • ###项目技术发展史
  • #微信小程序:微信小程序常见的配置传旨
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (2024,Flag-DiT,文本引导的多模态生成,SR,统一的标记化,RoPE、RMSNorm 和流匹配)Lumina-T2X
  • (26)4.7 字符函数和字符串函数
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)