微软面试题---求子数组最大乘积问题

最近从网上看到一个讨论较多的题目:

 

    “ 给定一个长度为N的整数数组,只允许用乘法,计算任意(N-1)个数的组合乘

积中最大的一组,并写出算法的时间复杂度。

 

分析:

(1) 按题目的要求,是求去掉一个元素后,剩下元素的乘积最大的那种组合。

(2) 整数数组,其元素可能取值为 : 正整数、负整数,和零。

(3) 设数组中有 p个零,    q 个 负数, r 个正数

     a ) 若 p>=2 则,

          任意 (N-1)个数的组合之积均为 0. 所以答案是:任意去除一个元素即可。

    b ) 若 p = 1   ( 原数组中含 一个 0 )

           若 q 为偶数             , 则 去掉 为0的元素即可

           若 q 为奇数,               则 去掉任意一个负数均可,

                                 乘积为0,是最大的,其他任意组合均小于0。

    c ) 当 p = 0时( 原数组中不含 “零” )

      当 q = 0 时   ( 不含负数时 )

                            去掉值最小的元素即可

      当 q 为奇数 时,

                           去掉绝对值最小的负数元素 即可

      否则:( 有偶数个负数 )

          如果   r >0   ( 即原数组中至少有一个正数 ):

                              去掉值最小的正数元素 即可      

  

         否则 ( 一个正数也没有, 也没有 0 ,全是负数 )

 

                      去掉绝对值最大的负数元素即可。    

                     

根据这个分析,程序不难设计出来。

 

 

    

 

讨论 :

       原题有“只允许用乘法”字样,不知是什么意思? 因为本算法中没有用到乘法,不知道,比较运算符是否允许使用? 本算法中,计算正数、负数、零的个数时,需用“加法”,如果不能用,就是原出题人思路有问题。

 

 

 

#coding=gbk
# 给定一个长度为N的整数数组, 计算任意(N-1)个数的组合
# 乘积中最大的一组,并写出算法的时间复杂度

def max_mult(   A ):
    p = 0   # 数组中 零的个数
    q = 0   # 数组中 负数的个数
    r = 0   # 数组中 正数的个数
    pos_0         = -1    # 首次 “0” 出现的位置
    pos_max_fu    = -1    # 绝对值最大的负数所在的位置
    pos_min_fu    = -1    # 绝对值最小的负数所在的位置
    pos_min_zhen = -1    # 最小正数 的位置
    for i in range(0,len(A)):
        x   = A[ i ]
        if x == 0:
            p = p +1
            if pos_0 == -1:
                pos_0 = i
        elif x<0:
            q = q +1
            if q==1:
                pos_max_fu,pos_min_fu = i,i
            else:
                if -x > -A[ pos_max_fu ] :
                    pos_max_fu = i
                elif -x < -A[ pos_min_fu ] :
                    pos_min_fu = i
        else:
            r = r +1
            if r==1:
                pos_min_zhen = i
            elif x < A[ pos_min_zhen ]:
                 pos_min_zhen = i
    if p>=2:
       return A[0:pos_0]+A[pos_0+1:]
    if p==1:
        if (q % 2)==0:
           return A[0:pos_0]+A[pos_0+1:]
        return A[0:pos_min_fu]+A[pos_min_fu+1:]
    if q==0:
        return A[0:pos_min_zhen]+A[pos_min_zhen+1:]
    if (q%2) == 1:
       return A[0:pos_min_fu]+A[pos_min_fu+1:]
    if r>0:
       return A[0:pos_min_zhen]+A[pos_min_zhen+1:]
    return A[0:pos_max_fu]+A[pos_max_fu+1:]

a = [ 0,0,4,1,5]
print( a, max_mult(a) )
a = [ 0,1,4,1,5]
print( a, max_mult(a) )
a = [ 0,-1,4,1,5]
print( a, max_mult(a) )
a = [ 0,-1,4,-3,5,-8]
print( a, max_mult(a) )

a = [ 0,-5,4,-1,5]
print( a, max_mult(a) )

a = [ 2,-3,4,-1,5,-8]
print( a, max_mult(a) )
a = [ -3,4,-1,-5,-8,2]
print( a, max_mult(a) )
a = [ -3,-4,-1,-5 ]
print( a, max_mult(a) )

a = [ -3,-4,-1,-5 ,-7]
print( a, max_mult(a) )

结果:(为了便于观察结果是确,我们下面的结果中,左侧是原数组,右侧是求出的数组:)

[0, 0, 4, 1, 5] [0, 4, 1, 5]
[0, 1, 4, 1, 5] [1, 4, 1, 5]
[0, -1, 4, 1, 5] [0, 4, 1, 5]
[0, -1, 4, -3, 5, -8] [0, 4, -3, 5, -8]
[0, -5, 4, -1, 5] [-5, 4, -1, 5]
[2, -3, 4, -1, 5, -8] [2, -3, 4, 5, -8]
[-3, 4, -1, -5, -8, 2] [-3, 4, -1, -5, -8]
[-3, -4, -1, -5] [-3, -4, -1]
[-3, -4, -1, -5, -7] [-3, -4, -5, -7]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值