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

Leetcode 152. 乘积最大子数组(Medium)

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 

子数组

(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

测试用例的答案是一个 32-位 整数。

示例 1:

输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

示例 2:

输入: nums = [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

提示:

  • 1 <= nums.length <= 2 * 104
  • -10 <= nums[i] <= 10
  • nums 的任何子数组的乘积都 保证 是一个 32-位 整数

思路:根据给的提示,是整数而且范围没有超int,所以只需要考虑负数和0的特殊情况,且数据类型只有int,所以只需要在遍历时当遇到负数或者0时,记录一下(当时的坐标+1),因为只有<=0,才会让数值有异常。然后分别把坐标0和不是最后一个结点的非正数的情况放到list里作为每次遍历的起始节点,然后取每次遍历的最大值。模拟一下,假如nums = [2,3,-2,4],先把坐标0的放进去,list=[0],然后向下走,走到-2时候<=0,且不是最后一个节点,放进去,list=[0, 3],(注意:放进去的节点是以后要遍历的所以是异常节点的后一位)。最后开始遍历一个遍历的max是6,第二次是4,所以最终的max是6,具体实现:

class Solution {
    public int maxProduct(int[] nums) {
        // 当前数值
        int cur = 1;
        // 最大值
        int max = Integer.MIN_VALUE;
        // 回退坐标值
        List<Integer> backIndexs = new ArrayList<>();

        for (int i = 0; i < nums.length; i++) {
            if (i == 0) backIndexs.add(0);
            if (nums[i] <= 0 && i != nums.length-1) {
                // 说明是负数或0,就记录一下
                backIndexs.add(i+1);
            }
        }
        while(!backIndexs.isEmpty()) {
            for (int i = backIndexs.remove(0); i < nums.length; i++) {
                cur *= nums[i];
                if(cur > max) max = cur;
            }
            cur = 1;
        }

        return max;
    }
}

还有一种思路,实际上大同小异,只是第一种,使用了集合,会导致性能的下降。第二种办法使用一次遍历,维护了三个属性值,局部最大值,局部最小值,最大值,当为结点负数的时候,局部最大值和局部最小值交换,局部最小值,就是去维护了负数的最大值,局部最大值就是维护的正数的最大值,当下一个负数出现时,min就需要和max换顺序,-max 必然小于等于 -min,max必然大于等于min

class Solution {  
    // 该方法用于找到给定整数数组中连续子数组的最大乘积  
    public int maxProduct(int[] nums) {  
        // 如果数组为空或长度为0,则没有乘积可以计算,直接返回0  
        if (nums == null || nums.length == 0) return 0;  
  
        // maxSoFar 用于记录到目前为止找到的最大乘积  
        int maxSoFar = nums[0];  
        // maxEndingHere 用于记录以当前元素结尾的连续子数组的最大乘积  
        int maxEndingHere = nums[0];  
        // minEndingHere 用于记录以当前元素结尾的连续子数组的最小乘积(考虑到负数乘以负数可能变成最大乘积)  
        int minEndingHere = nums[0];  
  
        // 遍历数组中的每个元素(从第二个元素开始,因为第一个元素已经在初始化时考虑过)  
        for (int i = 1; i < nums.length; i++) {  
            // 如果当前元素是负数,则交换 maxEndingHere 和 minEndingHere  
            // 这是因为负数乘以当前的最大值可能变成最小值,而乘以当前的最小值(实际上是绝对值最大的负数)可能变成最大值  
            if (nums[i] < 0) {  
                int temp = maxEndingHere;  
                maxEndingHere = minEndingHere;  
                minEndingHere = temp;  
            }  
  
            // 更新以当前元素结尾的连续子数组的最大乘积  
            // 如果当前元素本身就比之前的最大乘积还大,或者之前的最大乘积乘以当前元素更大,则更新 maxEndingHere  
            maxEndingHere = Math.max(nums[i], maxEndingHere * nums[i]);  
  
            // 更新以当前元素结尾的连续子数组的最小乘积  
            // 如果当前元素本身就比之前的最小乘积还小,或者之前的最小乘积乘以当前元素更小(考虑负数情况),则更新 minEndingHere  
            minEndingHere = Math.min(nums[i], minEndingHere * nums[i]);  
  
            // 更新到目前为止找到的最大乘积  
            // 如果以当前元素结尾的最大乘积比之前记录的最大乘积还大,则更新 maxSoFar  
            maxSoFar = Math.max(maxSoFar, maxEndingHere);  
        }  
  
        // 返回到目前为止找到的最大乘积  
        return maxSoFar;  
    }  
}


http://www.kler.cn/a/294945.html

相关文章:

  • 障碍检测与避障控制 ROS2机器人
  • LeetCode【0018】四数之和
  • 类型转换指令及方法调用与返回指令
  • 高德地图通过经纬度查找位置和轨迹回放
  • 飞凌嵌入式FET527N-C核心板现已适配Android 13
  • 【数据结构】线性表——链表
  • 通信工程学习:什么是ARQ自动重传请求
  • 【计算机视觉】语义分割输入图像尺寸
  • 快速傅里叶变换(FFT)及其在多项式乘法中的应用 —— 深入分析与 Python 实现
  • android AccessibilityService合法合规采集大众点评app商店商品详情(2024-09-02)
  • 【Qt笔记】QListWidget控件详解
  • 经济管理专业数据库介绍
  • 算法学习:模拟
  • Unity Adressables 使用说明(三)构建内容(Build Content)
  • 85、 探针
  • Java基础 1. Java开发环境搭建
  • 数据处理与数据填充在Pandas中的应用
  • 基于 RocketMQ 的云原生 MQTT 消息引擎设计
  • 智能体叙事实验:MixlabNodes新增Her页面
  • Android --- observer和observerForever的区别
  • Ansible自动化运维入门:从基础到实践的全面指南
  • 福建聚鼎科技:开一家装饰画店铺需要投资多少钱
  • Java|Java 中 JSONPath 的使用
  • history增加时间显示
  • PostgreSQL的repmgr工具介绍
  • centos基本命令