Maximum Product Subarray 以及cout的输出顺序问题的讨论

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],

the contiguous subarray [2,3] has the largest product = 6.

class Solution {
public:
    int maxProduct(int A[], int n) {
        int maxLocal = 1,minLocal = 1;
        int res = INT_MIN;
        for(int i = 0;i < n;++i)
        {
            int maxLocalTem = maxLocal;
            maxLocal = max(max(maxLocal * A[i],A[i]),minLocal * A[i]);
            minLocal = min(min(minLocal * A[i],A[i]),maxLocalTem * A[i]);
            res = max(res,maxLocal);
        }
        return res;
    }
};

动态规划

参考

Besides keeping track of the largest product, we also need to keep track of the smallest product. Why? The smallest product, which is the largest in the negative sense could become the maximum when being multiplied by a negative number.

Let us denote that:

f(k) = Largest product subarray, from index 0 up to k.

Similarly,

g(k) = Smallest product subarray, from index 0 up to k.

Then,

f(k) = max( f(k-1) * A[k], A[k], g(k-1) * A[k] )
g(k) = min( g(k-1) * A[k], A[k], f(k-1) * A[k] )

There we have a dynamic programming formula. Using two arrays of size n, we could deduce the final answer as f(n-1). Since we only need to access its previous elements at each step, two variables are sufficient.



至于怎么输出最大乘积的位置

我想的是在进行判断的时候记住位置即可 ,写的有一点复杂,但是还有是规律可以参考的,不知道有没有好的方法,但我觉得这种方法好理解一些

#include <iostream>

using namespace std;

class Solution
{
public:
    int start,end;
    Solution()
    {
        start =0;
        end = 0;
    }
    int maxProduct(int A[], int n)
    {

        int local_max = 1;
        int local_min = 1;
        int global = INT_MIN;
        int start_max = 0;
        int end_max = 0;
        int start_min = 0;
        int end_min = 0;
        for(int i = 0 ; i < n ; ++i)
        {
            int local_maxCopy = local_max;
            int start_maxTem = start_max;
            // local_max = max(max(A[i] * local_max,A[i]),A[i] * local_min);
            //local_min = min(min(A[i] * local_min,A[i]),local_ma * A[i]);
            //global = max(global,local_max);

            //max(A[i] * local_max,A[i])
            if(A[i] <= local_max * A[i])
            {
                local_max = local_max * A[i];
                end_max = i;
            }
            else
            {
                local_max = A[i];
                start_max = i;
                end_max = i;
            }
            // max(max(A[i] * local_max,A[i]),A[i] * local_min)
            if(local_max < A[i] * local_min)
            {
                local_max = A[i] * local_min;
                start_max = start_min;
                end_max = i;
            }
            //min(A[i] * local_min,A[i])
            if(A[i] < local_min * A[i])
            {
                local_min = A[i];
                start_min = i;
                end_min = i;
            }
            else
            {
                local_min = local_min * A[i];
                end_min = i;
            }
            //min(min(A[i] * local_min,A[i]),local_ma * A[i])
            if(local_min >= local_maxCopy * A[i])
            {
                local_min = local_maxCopy * A[i];
                start_min = start_maxTem;//这里应该是保存之前的local_max 和start_max的副本
                end_min = end_max;
            }
             // max(A[i] * local_max,A[i])
            if(global <= local_max)
            {
                global = local_max;
                start = start_max;
                end = end_max;
            }

        }

        return global;

    }
};

int main()
{
    Solution s;
    int a[] = {4,-3,-2,-222,2};
    cout<<s.maxProduct(a,5)<<endl;
    cout<<s.start<<" "<<s.end<<endl;
    return 0;
}

还有一点要注意的是cout的输出顺序问题

这个在网上搜了一下 发现以前好像还没注意这个问题。。。

就是在把

    cout<<s.maxProduct(a,5)<<endl;
    cout<<s.start<<" "<<s.end<<endl;
写成 

cout<<s.maxProduct(a,5)<<endl<<s.start<<" "<<s.end<<endl;
总是得不到正确结果 都是我设置的初始值

原来是cout的输出顺序导致的

cout流 在输出的时候从右往左压栈 然后在输出

在压栈的过程中会计算其中的值。。。

具体的可以看这个cout输出顺序

还可以看这个 cout输出流的执行顺序

以及这个例子

我问你一个你一定知道答案的问题:
int a=1;
cout<<(++a+(++a)+(++a))<<endl; 等于多少?
你肯定知道是12.(在devC++下是10,但是这个不用管,因为devC++下这是个BUG,你应该用更稳定支持C++的VC10去试它)
如果你不知道为什么是12,那么是因为这个表达式先执行了三次++a,再输出a+a+a。
这就是C++语法中俗称的“前副作用”,就是在“整个”表达式执行之前就运算完成的。

①首先:
  cout是什么?是一个类的实例化对象(某种流类型的)。
 
②其次:
  << 是什么?是操作符重载,实际上cout<<a  等效于cout.operator<<(a),也就是函数调用,函数名是operator<<   


如果我们把operator<< 这个函数名假设为 func
那么 cout<<a<<function(x)<<endl;
等效于 ((cout.func(a)).func(function(x))).func(endl);


③再次:
我问你一个你一定知道答案的问题:
int a=1;
cout<<(++a+(++a)+(++a))<<endl; 等于多少?
你肯定知道是12.(在devC++下是10,但是这个不用管,因为devC++下这是个BUG,你应该用更稳定支持C++的VC10去试它)
如果你不知道为什么是12,那么是因为这个表达式先执行了三次++a,再输出a+a+a。
这就是C++语法中俗称的“前副作用”,就是在“整个”表达式执行之前就运算完成的。


④最后:


你肯定也知道,我在③举的例子跟你的问题表面上不是一码事,但是其实还是一码事:
((cout.func(a)).func(function(x))).func(endl);  是一个表达式整体,


C++先会把所有优先级最高的运算先执行:
我们模拟一下编译器:


读到 cout.func(a)  此时a是最高优先级表达式,
但是a已经是变量本身,
所以跳过去找另一个高优先的表达式(注意,此时不是直接执行cout.func(a))
接着是.func(function(x)),
注意,第二个func是不能在第一个func之前先执行的,
但是实参却需要先执行,所以是执行function(x),接着再执行endl(其实不用执行,因为endl已经是最小粒度表达式)。
此时再回头执行第一个func,返回一个对象,接着调用这个返回了的对象的func(第二个func)。


所以表达式((cout.func(a)).func(function(x))).func(endl);  
等效于以下语句:
a;   => 结果是变量a (此时a没有压栈或者说没有被传入func函数)
x;   =>  结果是变量x 
function(x);   => 返回结果假设是K
endl;  =>结果是endl
cout.func(a);  => 结果是返回一个对象C
C.func(K);  => 结果是返回一个对象C2
C2.func(endl);  => 结果是返回一个对象C3


C++和C不同,C的 printf("%d",(++a)+(++a)+(++a)); 等效于 printf("%d",(1+a)+(2+a)+(3+a));
这是由于C编译器用的是比较古老的编译器设计观念。


还有最后一点,C++这种特性到逗号表达式(不包括实参列表)为止为最小粒度。


我们把((cout.func(a)).func(function(x))).func(endl);  改为:


((cout.func(a)).func(function(x))).func(endl),++a;   


后面的++a不会影响前面的函数调用。


而((cout.func(a)).func(function(++a))).func(endl);


会影响。


这就是因为逗号表达式是最小表达式粒度的原因 。  


⑤ 不知道你理解没有,


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值