今天跟项目经理聊完天,正好不要再操心项目的事情了,闲来没事就去看了下leetcode,发现又多了一题:

因为朋友面试的时候正好遇到了这题,这里就当记录一下。

英文题就不贴了,自己去看吧。意思就是求数组的最大子序列积。这个名字是如此的熟悉,最大子序列和是一道很经典的题目,网上可以搜到很多,比如这个人就写的很好,一看就懂:

换成积了,差别也不大。

O(N^2)解法

先说最朴质的解法,无非是遍历然后计算出所有的积,一一比较找到最大的罢了,跟和的第一种解法对应,于是我写下了这段代码:

int maxProduct(int A[], int n) {    int max = A[0];    for (int i = 1; i < n; ++i) {        int product = 1;        for (int j = i; j < n; ++j) {            product *= A[j];            if (product > max) {                max = product;            }        }    }    return max;}

根据leetcode的尿性,这样的解法肯定是超时的,果不其然,提交就超时。

O(N)解法

我没有去看怎么弄出一个o(nlgn)的解法,受到上面那个博客里第三解法的启发,在求最大子序列和的时候,递推公式是:Max[i] = max(Max[i-1] * A[i], A[i])。

仔细想想,积应该不光是这样,因为存在负负得正的乘法规则,所以 Max[i] 有可能是 i-1 中的负数积乘以 A[i] 得到,表征这样一种可能性,我们需要记录前 i-1 中的最小积,其实如果那个最小的积不是负数又或者就没有必要,所以

if (Min[i-1] < 0 && A[i] < 0)

    Max[i] = max(Max[i-1] * A[i],  Min[i-1] * A[i])

else

    Max[i] = max(Max[i-1] * A[i], A[i])

为了代码的简洁,懒得去判断正负号了,总之:Max[i] = max(Max[i-1] * A[i], Min[i-1] * A[i], A[i])。这样就可以写代码:

int max3(int a, int b, int c){    if ((a >= b) && (a >= c))        return a;    return max3(b, c, a);}int min3(int a, int b, int c){    if ((a <= b) && (a <= c))        return a;    return min3(b, c, a);}int maxProduct(int A[], int n) {    int max = A[0];    int maxtemp = A[0], mintemp = A[0];    int temp1 = 0, temp2 = 0;    for (int i = 1; i < n; ++i) {        temp1 = maxtemp * A[i];        temp2 = mintemp * A[i];        maxtemp = max3(temp1, temp2, A[i]);        mintemp = min3(temp2, temp1, A[i]);        if (maxtemp > max)            max = maxtemp;    }    return max;}

别看代码丑,提交过了哦:)