問題描述:長度爲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;i<a.length;i++){
int j=0;
int muti =1;
while(true){
if(j!=i){
mutil *=a[j];
}
j++;
if(j==a.length)
break;
}
if(max<mutil){
max =mutil;
index = i;
}
}
for(int i=0;i<a.length;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;i<a.length;i++){
if(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;i<a.length;i++){
if(a[i]>0&&cmp>a[i]){
cmp=a[i];
index=i;
}
}
}else if(flag<=-1) {
int cmp=0;
for(int i=0;i<a.length;i++){
if(a[i]<0&&cmp>a[i]){
cmp=a[i];
index=i;
}
}
} else {
int cmp=a[0];
for(int i=0;i<a.length;i++){
if(a[i]<0&&cmp<a[i]){
cmp =a[i];
index=i;
}
}
}
return index;
}
//打印
public void print(int index){
for(int i=0;i<a.length;i++){
if(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)