152. 乘积最大子序列

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 152. 乘积最大子序列

本题来自 LeetCode:152. 乘积最大子序列[1]

题目详情

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

示例 1:


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

示例 2:


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

题目分析

  • 定义`max` 为最大乘积,`currentMax`为当前最大乘积;
  • 显然`max = max(max, currentMax)`;
  • 若数组`nums`全为正整数,则`currentMax = currentMax * nums[i]`;
  • 由于数组中存在`0`,故`currentMax = max(currentMax * nums[i], nums[i])`;
  • 由于数组中存在负数,因此需要维护当前最小乘积`currentMin`:
  • 若`currentMin 0`、`nums[i] 0`,则`currentMin = min(currentMin * nums[i], nums[i])`;
  • 若`currentMin 0`、`nums[i] 0`,则`currentMin = min(currentMax * nums[i], nums[i])`;
  • 若`currentMin 0`、`nums[i] 0`,`currentMin = min(currentMax * nums[i], nums[i])`, `currentMax = max(currentMin * nums[i], nums[i])`;
  • 题目解答

    
    class Solution {
        public int maxProduct(int[] nums) {
            int max = Integer.MIN_VALUE;
    
            int currentMax = 1;
            int currentMin = 1;
            for(int i = 0; i  nums.length; i ++) {
                if(nums[i]  0) {
                    currentMax = currentMax ^ currentMin;
                    currentMin = currentMax ^ currentMin;
                    currentMax = currentMax ^ currentMin;
                }
    
                currentMax = Math.max(currentMax * nums[i], nums[i]);
                currentMin = Math.min(currentMin * nums[i], nums[i]);
    
                max = Math.max(max, currentMax);
            }
            return max;
        }
    }
    

    进一步可观察可发现, currentMax currentMin分别取这三个值 currentMax * nums[i] currentMin * nums[i] nums[i]的最大值和最小值。调整代码后:

    
    class Solution {
        public int maxProduct(int[] nums) {
            int max = Integer.MIN_VALUE;
    
            int currentMax = 1;
            int currentMin = 1;
            for(int i = 0; i  nums.length; i ++) {
                int tempMax = currentMax * nums[i];
                int tempMin = currentMin * nums[i];
    
                currentMax = Math.max(Math.max(tempMax, tempMin), nums[i]);
                currentMin = Math.min(Math.min(tempMax, tempMin), nums[i]);
    
                max = Math.max(max, currentMax);
            }
            return max;
        }
    }
    

    参考资料

    1. 乘积最大子序列: https://leetcode-cn.com/problems/maximum-product-subarray/

    原文始发于微信公众号(xiaogan的技术博客):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> 152. 乘积最大子序列


     上一篇
    LeetCode(347) 数组中的第 K 个最大元素(堆排序) LeetCode(347) 数组中的第 K 个最大元素(堆排序)
    一般情况下,题目中有出现前 N个最大(小)值 topN、第 k个最大(小)值,均可以用堆排序来解答,本文来学习下 堆排序的相关知识。 基本概念 堆排序( Heapsort)是指利用 堆所设计的一种排序算法。 堆是一个近似 完全二叉树的结构,
    2021-04-05
    下一篇 
    287. 寻找重复数 287. 寻找重复数
    本题来自 LeetCode:287. 寻找重复数[1] 题目详情给定一个包含 n + 1个整数的数组 nums,其数字都在 1到 n之间(包括 1和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。 示例 1:
    2021-04-05