[经典面试题]最大连续乘积

简介:

题目

给一个浮点数序列,取最大乘积连续子串的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积连续子串为3,0.5,8。也就是说,上述数组中,3 0.5 8这3个数的乘积3*0.5*8=12是最大的,而且是连续的。

分析

最大乘积连续子串与最大乘积子序列不同,前者子串要求连续,后者子序列不要求连续。初看此题,自然会想到最大连续乘积问题类似于最大子数组和问题

思路一 穷举法

穷举子串的起点和终点。

代码一

/*---------------------------------------------
*   日期:2015-02-14
*   作者:SJF0115
*   题目: 最大连续乘积
*   来源:
*   博客:
-----------------------------------------------*/
#include <iostream>
#include <cstring>
using namespace std;

class Solution {
public:
    double MaxProduct(double num[],int n){
        if(n <= 0){
            return 0;
        }//if
        double max = num[0];
        double cur;
        int start = 0,end = 0;
        // 起点
        for(int i = 0;i < n;++i){
            cur = 1;
            // 终点
            for(int j = i;j < n;++j){
                cur *= num[j];
                if(cur > max){
                    max = cur;
                    start = i;
                    end = j;
                }//if
            }//for
        }//for
        cout<<"start->"<<start<<" end->"<<end<<endl;
        return max;
    }
};


int main() {
    Solution solution;
    double num[] = {-2.5,4,0,3,0.5,8,-1};
    cout<<solution.MaxProduct(num,7)<<endl;
}

思路二

虽说类似于最大子数组和问题,但实际上有很多细节不同。因为当前最大子数组和只与前一个的最大和有关,但是乘积则不同。乘积会由于负负得正的原因,我们不仅会记录当前最大乘积还要记录当前最小乘积。

代码二

/*---------------------------------------------
*   日期:2015-02-15
*   作者:SJF0115
*   题目: 最大连续乘积
*   来源:
*   博客:
-----------------------------------------------*/
#include <iostream>
#include <cstring>
using namespace std;

class Solution {
public:
    double MaxProduct(double num[],int n){
        if(n <= 0){
            return 0;
        }//if
        double max = num[0];
        double curMax = 1,curMin = 1;
        int maxStart = 0,maxEnd = 0,minStart = 0,minEnd = 0;
        int start = 0,end = 0;
        // 起点
        for(int i = 0;i < n;++i){
            curMax *= num[i];
            curMin *= num[i];
            // 从curMax*num[i] curMin*num[i] num[i]
            // 找到当前最大值和当前最小值
            if(curMax < curMin){
                swap(curMax,curMin);
                maxEnd = i;
                minEnd = i;
                //cout<<"i->"<<i<<endl;
                swap(maxStart,minStart);
                //cout<<"min("<<minStart<<","<<minEnd<<")"<<endl;
                //cout<<"max("<<maxStart<<","<<maxEnd<<")"<<endl;
            }//if
            // 从num[i]重新开始
            // 更新当前最大值
            if(curMax < num[i]){
                curMax = num[i];
                maxStart = i;
            }//if
            maxEnd = i;

            // 更新当前最小值
            if(curMin > num[i]){
                curMin = num[i];
                minStart = i;
            }//if
            minEnd = i;

            if(curMax > max){
                max = curMax;
                start = maxStart;
                end = maxEnd;
            }//if
        }//for
        cout<<"最大连续乘积区间("<<start<<","<<end<<")"<<endl;
        return max;
    }
};


int main() {
    Solution solution;
    double num[] = {-2.5,-4,1,-3,0,8,1};
    cout<<solution.MaxProduct(num,7)<<endl;
}

思路三

这一题目可以用动态规划求解。其实,上述思路本质上也是动态规划,只是解题所表现出来的具体形式跟动态规划不太一样。
假设数组为num[],考虑到可能存在负数的情况,我们用Max来表示以num[i]结尾的最大连续乘积值,用Min表示以num[i]结尾的最小连续乘积值。
状态转移方程为:
这里写图片描述
初始状态为Max[0]=Min[0]=num[0]。

代码三

/*---------------------------------------------
*   日期:2015-02-15
*   作者:SJF0115
*   题目: 最大连续乘积
*   来源:
*   博客:
-----------------------------------------------*/
#include <iostream>
#include <cstring>
using namespace std;

class Solution {
public:
    double MaxProduct(double num[],int n){
        if(n <= 0){
            return 0;
        }//if
        double Max[n] ,Min[n],maxVal = num[0];
        Max[0] = Min[0] = num[0];
        for(int i = 1;i < n;++i){
            Max[i] = max(max(num[i],Max[i-1]*num[i]),Min[i-1]*num[i]);
            Min[i] = min(min(num[i],Max[i-1]*num[i]),Min[i-1]*num[i]);
            maxVal = max(maxVal,Max[i]);
        }//for
        return maxVal;
    }
};


int main() {
    Solution solution;
    double num[] = {-2.5,-4,1,3,0,8,5};
    cout<<solution.MaxProduct(num,7)<<endl;
}

相似题目

[经典面试题]子数组的最大乘积

目录
相关文章
|
算法 C++ 索引
【力扣经典面试题】238. 除自身以外数组的乘积
【力扣经典面试题】238. 除自身以外数组的乘积
[leetcode/lintcode 题解] 国内大厂面试高频题: 数组除了自身的乘积
[leetcode/lintcode 题解] 国内大厂面试高频题: 数组除了自身的乘积
[leetcode/lintcode 题解] 国内大厂面试高频题: 数组除了自身的乘积
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
10月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
10月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
10月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
249 4
|
11月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
867 2
|
11月前
|
JSON 安全 前端开发
第二次面试总结 - 宏汉科技 - Java后端开发
本文是作者对宏汉科技Java后端开发岗位的第二次面试总结,面试结果不理想,主要原因是Java基础知识掌握不牢固,文章详细列出了面试中被问到的技术问题及答案,包括字符串相关函数、抽象类与接口的区别、Java创建线程池的方式、回调函数、函数式接口、反射以及Java中的集合等。
137 0
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。