乘积最大子数组[前缀积 + 内在规律限定下的逻辑转换]

前言

前缀积思想,题前抽象一段子数组(积/和/自定义处理方式),通过空间换时间。前缀和的本质就是简单的动态规划,有时可以空间压缩,这样就不浪费空间了。

逻辑转换思想,在一些内在规律的限定下,可以另辟蹊径,就是一种逻辑转换,以达到走捷径,减运算消耗时间&空间的目的。达到一个目的的直观路径有一条,但观察其规律,将问题转换 / 将过程转换,用更简洁的逻辑来表达,便发现了多条殊途同归的路,也算是算法的目的吧。

一、乘积的最大子数组

在这里插入图片描述

二、前缀积&逻辑转换

1、idea

子数组的任何前缀乘积都不超过32位;
数肯定是越乘越大,除非碰到0,开启新一段数据;
每段数组处理方式,记录当前乘积,记录当前段最前面的负数积,如果当前乘积是负数,将最前面的负数积除掉,再更新最大乘积max,反之直接用来更新max最大乘积。

2、golang简洁版

func maxProduct(nums []int) int {
    m := nums[0]
    all,neg := 1,1
    for _,n := range nums {
        // 记录当前乘积
        all *= n
        // 取最大乘积
        m = max(max(all,all / neg),m) // 用时4ms -> 0ms
        // 开启下一段数组的neg 和 all
        if n == 0 {
            neg = 1
            all = 1
        }
        // 记录该段第一个负数积
        if n < 0 && neg == 1 {
            neg = all
        }  
    }
    return m
}
func max(x,y int) int {
    if x > y {
        return x
    }
    return y
}

3、golang解析版

func maxProduct(nums []int) int {
    m := nums[0]
    all,neg := 1,1
    for _,n := range nums {
        // 记录当前乘积
        all *= n
        // 记录最大乘积,2种情况,负数/负数  & 正数
        /*
        k := 0
        if all >= 0 {
            k = all
        }else {
            k = all / neg
        }
        if k > max {
            max = k
        }
        */
        // 抽象过程,逻辑等价替换。
        // 这个if/else可用max函数替换,通过内在规律限定,无非就是取最大。
        m = max(max(all,all / neg),m) // 用时4ms -> 0ms
        // 开启下一段数组的neg 和 all
        if n == 0 {
            neg = 1
            all = 1
        }
        // 记录该段第一个负数
        if n < 0 && neg == 1 {
            // 真正的负数必须带上前面所有的正数乘积
            neg = all
        }  
    }
    return m
}
func max(x,y int) int {
    if x > y {
        return x
    }
    return y
}

// 逻辑整理,检验基本功是否准备好?
// 子数组的任何前缀乘积都不超过32位
// 越乘肯定越大,除非碰到0,每段找到最前面的那个负数,以便后续需要。
// case:从左到右遍历,同时记录当前乘积,以及最前面那个负数,负数初始化为1,不更新最大乘积即可。

总结

1)前缀思想,一种抽象的思想,可以是前缀积/前缀和,也可以是自定义前缀xx.
2)逻辑转换思想,目的清晰,暴力路径一条,但可以挖掘内在规律,发现其他路径。这条路径可以是抽象问题,改变程序整体结构,降低整个程序的时空复杂度;也可以是抽象其中一个小目的,改变一小段代码,提高运算速度。

参考文献

[1] LeetCode 乘积最大子数组

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值