题解
题意:给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组 (该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 题解:此题要求找到连续乘积最大的子数组,连续数组的意义是什么,一个最直观的想法就是,如果前面的乘积在乘了元素i
之后变大了,那么就把元素i
加入到子数组中,否则,则从第i
项开始,再进行记录。
但是这会遇到一个问题,正数如果乘以负数,那么就是变小了,此时如果抛弃掉前面的项,很明显是不对的,因为后面如果又遇到一个负数,那么最小值又变成最大值了,因此我们不能因为乘以了一个负数,就单纯抛弃前面的项。 此时问题似乎变复杂了,但是最大乘积只可能是最小值乘以负数 ,或者最大值乘以正数 得到,因此我们维护一个最小值序列与最大值序列即可,这个状态转移就简单了,就是到第i
个项的时候,最大值是从前i-1
项的最大乘积得到,还是最小乘积得到,当然,也可能是当前元素,比如前面乘积最大值是负数,突然来了一个正数,那此时最大乘积数值就是它。
m
a
x
[
i
]
=
M
A
X
(
m
a
x
[
i
−
1
]
∗
n
u
m
s
[
i
]
,
M
A
X
(
n
u
m
s
[
i
]
,
m
i
n
[
i
−
1
]
∗
n
u
m
s
[
i
]
)
)
max[i]=MAX(max[i-1]*nums[i], MAX(nums[i], min[i-1]*nums[i]))
m a x [ i ] = M A X ( m a x [ i − 1 ] ∗ n u m s [ i ] , M A X ( n u m s [ i ] , m i n [ i − 1 ] ∗ n u m s [ i ] ) )
m
i
n
[
i
]
=
M
I
N
(
m
i
n
[
i
−
1
]
∗
n
u
m
s
[
i
]
,
M
I
N
(
n
u
m
s
[
i
]
,
m
a
x
[
i
−
1
]
∗
n
u
m
s
[
i
]
)
)
min[i]=MIN(min[i-1]*nums[i], MIN(nums[i], max[i-1]*nums[i]))
m i n [ i ] = M I N ( m i n [ i − 1 ] ∗ n u m s [ i ] , M I N ( n u m s [ i ] , m a x [ i − 1 ] ∗ n u m s [ i ] ) ) 实现: ,
class Solution {
public int maxProduct ( int [ ] nums) {
int n = nums. length;
int [ ] max = new int [ n] ;
int [ ] min = new int [ n] ;
int maxv = nums[ 0 ] ;
max[ 0 ] = nums[ 0 ] ;
min[ 0 ] = nums[ 0 ] ;
for ( int i = 1 ; i < n; ++ i) {
max[ i] = Math. max ( max[ i - 1 ] * nums[ i] , Math. max ( nums[ i] , min[ i - 1 ] * nums[ i] ) ) ;
min[ i] = Math. min ( min[ i - 1 ] * nums[ i] , Math. min ( nums[ i] , max[ i - 1 ] * nums[ i] ) ) ;
maxv = Math. max ( maxv, Math. max ( min[ i] , max[ i] ) ) ;
}
return maxv;
}
} ;
我们可以发现,其实不需要开两个数组来存储max
和min
,因为这两个数字可以相互转换,当遇到负数的时候,最大正数乘积可能会被转换成最小负数乘积,而最小负数乘积就可能会变成最大正数乘积, 而最大乘积也只可能在这两种情况下得到。
举个例子,对于[1,2,3,4,-1,-2]
来说,最小乘积数组是[1,2,3,4,-1]
,最大则是[1,2,3,4,-1,-2]
,是由最小乘积得到的,但是由最小乘积转换来的正数不一定是最大乘积,比如[1,2,3,4,-1,-2, -1, 1,2,3,4,5]
,是由[-2,-1,1,2,3,4,5]
数组得到的。 那么这样一来,我们还是需要额外利用一个max
来记录过程中的最大值,因为最大乘积只可能从最小乘积的下一个状态和最大乘积中获取 实现
class Solution {
public int maxProduct ( int [ ] nums) {
int max = nums[ 0 ] ;
int imin = nums[ 0 ] , imax = nums[ 0 ] ;
int n = nums. length;
for ( int i = 1 ; i < n; i++ ) {
if ( nums[ i] < 0 ) {
imin = imax^ imin;
imax ^= imin;
imin ^= imax;
}
imax = Math. max ( nums[ i] , imax* nums[ i] ) ;
imin = Math. min ( nums[ i] , imin* nums[ i] ) ;
max = Math. max ( max, imax) ;
}
return max;
}
}
题目