长度为n的整形数组,找出其中的任意n-1个数乘积最大的那一组

问题描述:长度为n的整形数组,找出其中的任意n-1个数乘积最大的那一组,可以用乘法,但不能用除法,要求对算法处理的 时间复杂度和空间复杂度做出分析。

方法一:

首先能想到的一般方法就是暴力求解法。假设去掉第一个元素,求剩下n-1个乘积赋值给max,同时记录下下标index;然后假设第二个元素去掉,求剩下n-1个的乘积,若比前一个大则max等于当前值,index更新。重复此过程一直到最后一个元素。最后得到的max就是除去下标为index的n-1个元素乘积的最大值。

int max=0;
int index=0;
for(int i=0;ilength;i++){
    int j=0;
    int muti =1;
    while(true){
     if(j!=i){
        mutil *=a[j];
     }
     j++;
     if(j==a.length)
     break;
   }
   if(maxindex = i;
     }
}

for(int i=0;ilength;i++){
   if(index!=i)
   System.out.print(a[i]+ " ");
}

方法的时间复杂度为O(n^2),空间复杂度为O(1)

方法二:

既然事先给定n给整数,那么其乘积是一定的。不妨设这n个数的乘积为P,那么求n-1个数的乘积的最大值只需求P/a[i]的最大值。而题目要求说不能使用除法,那么转化思路。P/a[i]=(P*a[i])/a[i]^2,其中a[i]^2一定是正数,可以发现P/a[i]和P*a[i]同正负。现在我们可以把P/a[i]跟P*a[i]联系起来。
P的可能取值可能为正、负和0。

a. P值为正的情况。
问题转化求Max(P/a[i]),如果此时有至少一个a[m]为正值,那么Max(P/a[i])必定为正值,所以P*a[i]也必定为正值i(指数组元素为正值的下标)。因为P为正值,且P*a[i]的值越大表明a[i]的值越大,那么P/a[i]的值就会越小;P*a[i]的值越小表明a[i]的值越小,那么P/a[i]的值就会越大。那么问题转化为求P*a[i]的最小正值,即求a[i]的最小正值,剩余n-1个元素的乘积最大。
如果此时a[i]全为负值,那么找出a[i]中最小的那个,剩余n-1个元素的乘积最大。

  • b.P为负值的情况
    问题还是求Max(P/a[i]),那么此时有至少一个a[m]为负值,那么Max(P/a[i])必定为正值,所以P*a[i](i指数组元素为负值的下标)也必定为正值。因为P为负值,且P*a[i]的值越大表明a[i]的值越小,也就是a[i]的绝对值越大,那么P/a[i]的值就会越小;P*a[i]的值越小表明a[i]的值越大,a[i]为负数绝对值越小,那么P/a[i]的值就会越大。那么问题转化为求P*a[i]的最小正值,此处P为负值,所以应该求负数集合a[i]中的最大值,对应绝对值最小。

  • c.P为0的情况
    P为0 ,意味着数组中存在至少一个0。
    找出为0 的元素,若大于一个,那么n-1个元素的最大值乘积为0此,只要包含0元素的集合均满足条件,也就是任取n-1个元素(题目是说求一组,应该不会出现这种情况);若只有一个,那么求出0元素以外的乘积,若该乘积为负,则n-1个元素的最大乘积为0,只要包含0的元素集合均满足条件。若该乘积为正,则除0元素的外的n-1个满足条件。

  • 结论:
    n个元素的乘积为正,且有元素为正,那么排除该正整数集中的最小值剩下的n-1个元素即为所求。若n个元素全为负,则找负正整数集中的最小值,排除该元素后剩余的n-1个即为所求。
    n个元素的乘积为负,那么找出该负正整数集中最大的元素,排除该元素后,剩余的元素即为所求。
    有一个0元素,求其余元素的正负;有两个0元素,任意n-1个元素均满足条件。

public class FindNum{
      private static    int zero =0;//0元素个数
      private static    int zeroIndex=0;//0元素所在位置
      private static    int positiveCounts =0;//正整数个数
      private static    int negitiveCounts =0;//负整数个数
      private static    int p=1;//标志N个数的乘积的正负
      private static    int index =0;//待排除元素的下标

  public void init(){
        for(int i=0;iif(a[i]==0){
                zero++;
                zeroIndex=i;
            }else if(a[i]>0){
                positiveCounts++;
            }else {
               negitiveCounts++;
            }
        }
 }
 //求乘积的正负
  public int getP(int zero ,int negitiveCounts){
         if(zero!=0) return 0;
         if(negitiveCounts%2==0) return 1;
         return -1;
 }   

//flag=1,找正整数集中最小值;flag =-1,找负整数集的最小值;
//flag=0,找负整数集中最大值。
    public int    getIndex(int flag){
         int index=0;
         if(flag>=1){
             int cmp=0;
             for(int i=0;iif(a[i]>0&&cmp>a[i]){
                     cmp=a[i];
                     index=i;
                }
           }
      }else if(flag<=-1) {
           int cmp=0;
          for(int i=0;iif(a[i]<0&&cmp>a[i]){
                   cmp=a[i];
                   index=i;
               }
         }
       } else {
            int cmp=a[0];
           for(int i=0;iif(a[i]<0&&cmpreturn index;
}     


    //打印
    public void print(int index){
         for(int i=0;iif(index!=i)
            System.out.print(a[i]+ " ");
       }
    }

public static void main(String [] args){
    FindNum f = new FindNum();
     f.init();
     p=getP(0,negitiveCounts);
     if(zero=1){
          if(p>0)  print(zeroIndex);
          else if(p<0) 包含0的n-1个元素都可以
       } else if(zero>1){
            任意N-1个元素都可以
       } else {
           if(p>0){
                if(positiveCounts>0){
                     index =getIndex(1);//返回正整数集中最小值
               }else {
                    index = getIndex(-1);//返回负整数集中最小值
               }
           }else if(p<0){
                 index = getIndex(0);//返回负整数中的最大值
         }
          print(index); 
     }
} 

该算法的时间复杂度为O(n),空间复杂度为O(1)

你可能感兴趣的:(算法)