今天跟项目经理聊完天,正好不要再操心项目的事情了,闲来没事就去看了下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;}
别看代码丑,提交过了哦:)