1. 程式人生 > >求排列A',使得advantage(A',B)最大

求排列A',使得advantage(A',B)最大

(這道題目是在不知道起個什麼名字好,就把題中關鍵的內容作為題目了)

題目

給定兩個長度相等都為n的陣列A和陣列B,定義advantage(A,B)等於A[i]>B[i]元素的個數,要求寫一個enhance函式,輸入A,B,返回一個排列A',使得advantage(A',B)最大,並給出時間複雜度。

舉例1

A=【2,7,11,15】,B=【1,10,4,11】

則advantage(A,B)=3(2>1,7<10,11>4,15>11)

利用你寫的enhance函式,可以得到A'=enhance(A,B)=【2,11,7,5】,使avantage(A',B)=4(2>1,11>10,7>4,15>11)

舉例2

A=【12,24,8,32】,B=【13,25,32,11】

A'=enhance(A,B)=【24,32,8,12】

avantage(A',B)=3(24>13,32>25,8<32,12>11)

思路

(宣告:這道題是同學問我的一道題,思路沒有驗證過,不知道對不對,希望看到這道題的你可以幫忙驗證一下)

  • 求a陣列,那麼從a數組裡找數,和b陣列比較:
    • b陣列第一個,a數組裡有沒有比他大的,
      • 沒有的話,a陣列第一個數字就從老a數組裡最小的一個作為這個數(同時老a數組裡除去這個數【這一步操作的程式碼需要好好理解】
      • 若有比他大的,就從所有比他大的數字裡邊找到最小的一個數字作為這個數字,(同時老a數組裡除去這個數)
    • 以此類推

程式碼(遞迴實現)

思路已經明瞭,開始寫程式碼吧

雖然邏輯很清楚,實現出來的程式碼的邏輯你可能會看暈,所以這裡分佈來介紹我的程式碼(嫌麻煩的話直接看最終程式碼)

  • 將目標陣列直接輸出的程式碼(實際上程式碼裡並沒有將數字儲存在數組裡,只是直接輸出數字)
  • 將目標陣列儲存倒數組裡的程式碼(儲存到數組裡的順序是逆順序的)
  • 將目標陣列儲存倒數組裡的程式碼(儲存到數組裡的順序是順序的)【最終程式碼】

將目標陣列直接輸出的程式碼(實際上程式碼裡並沒有將數字儲存在數組裡,只是直接輸出數字)

public static void shuzu(int[] a,int[] b){
		if(a.length<=0){
			return ;
		}else{//這裡分情況討論
			int flag=0;//設定標記,a裡有大於b的則為1,沒有則為0
			int min_a=1000000;//記錄a數組裡最小的一個
			int min_a_flag=0;//記錄a數組裡最小的一個的座標
			int min=10000000;//假設有的話。用min來表示裡邊最小的一個
			int min_flag=0;//記錄min的座標
			for(int i=0;i<a.length;i++){
				
				if(a[i]>b[0]){//總是比較b的第一個
					flag=1;
					if(a[i]<min){
						min=a[i];
						min_flag=i;
					}
				}
				if(a[i]<min_a){
					min_a=a[i];
					min_a_flag=i;
				}
			}
			if(flag==0){//如果沒有大的
				//輸出a裡最小的 
				System.out.println(min_a);
				//進行下一個遞迴(a、b陣列都減1個長度)
				int[] a_new=new int[a.length-1];
				int[] b_new=new int[a.length-1];
				for(int i=0;i<a.length-1;i++){//將a減少一個長度,去掉那個小的數
					if(i>=min_a_flag){
						a_new[i]=a[i+1];
					}else{
						a_new[i]=a[i];
					}
				}
				for(int i=1;i<a.length;i++){
					b_new[i-1]=b[i];
				}
				shuzu(a_new,b_new);
			}else{
				//輸出大的裡邊的最小的 
				System.out.println(min);
				//進行下一個遞迴(a、b陣列都減1個長度)
				int[] a_new=new int[a.length-1];
				int[] b_new=new int[a.length-1];
				
				for(int i=0;i<a.length-1;i++){//將a減少一個長度,去掉那個小的數
					if(i>=min_flag){
						a_new[i]=a[i+1];
					}else{
						a_new[i]=a[i];
					}
				}
				for(int i=1;i<a.length;i++){
					b_new[i-1]=b[i];
				}
				shuzu(a_new,b_new);
			}
		}
	}

將目標陣列儲存倒數組裡的程式碼(儲存到數組裡的順序是逆順序的)

我們在遞迴裡傳入一個引數:陣列c,每次遞迴都把那個數傳給陣列c,下標是陣列a的長度-1,因為每次遞迴陣列a都會減少1,這樣陣列c就是我們所求的陣列啦

public static void shuzu(int[] a,int[] b,int[] c){
		if(a.length<=0){
			return ;
		}else{//這裡分情況討論
			int flag=0;//設定標記,a裡有大於b的則為1,沒有則為0
			int min_a=1000000;//記錄a數組裡最小的一個
			int min_a_flag=0;//記錄a數組裡最小的一個的座標
			int min=10000000;//假設有的話。用min來表示裡邊最小的一個
			int min_flag=0;//記錄min的座標
			for(int i=0;i<a.length;i++){
				
				if(a[i]>b[0]){//總是比較b的第一個
					flag=1;
					if(a[i]<min){
						min=a[i];
						min_flag=i;
					}
				}
				if(a[i]<min_a){
					min_a=a[i];
					min_a_flag=i;
				}
			}
			if(flag==0){//如果沒有大的
				//輸出a裡最小的 
				System.out.println(min_a);
				c[a.length-1]=min_a;
				//進行下一個遞迴(a、b陣列都減1個長度)
				int[] a_new=new int[a.length-1];
				int[] b_new=new int[a.length-1];
				for(int i=0;i<a.length-1;i++){//將a減少一個長度,去掉那個小的數
					if(i>=min_a_flag){
						a_new[i]=a[i+1];
					}else{
						a_new[i]=a[i];
					}
				}
				for(int i=1;i<a.length;i++){
					b_new[i-1]=b[i];
				}
				shuzu(a_new,b_new,c);
			}else{
				//輸出大的裡邊的最小的 
				System.out.println(min);

				c[a.length-1]=min;
				//進行下一個遞迴(a、b陣列都減1個長度)
				int[] a_new=new int[a.length-1];
				int[] b_new=new int[a.length-1];
				
				for(int i=0;i<a.length-1;i++){//將a減少一個長度,去掉那個小的數
					if(i>=min_flag){
						a_new[i]=a[i+1];
					}else{
						a_new[i]=a[i];
					}
				}
				for(int i=1;i<a.length;i++){
					b_new[i-1]=b[i];
				}
				shuzu(a_new,b_new,c);
			}
		}
	}

將目標陣列儲存倒數組裡的程式碼(儲存到數組裡的順序是順序的)

為了保證c數組裡的數是順序的,我們在遞迴裡再傳入一個引數,初始a的長度,這個引數不隨著遞迴變化,這樣在c數組裡的下標改成length-a.length,所求的陣列就是順序的啦。

public static void shuzu(int[] a,int[] b,int[] c,int length){
		if(a.length<=0){
			return ;
		}else{//這裡分情況討論
			int flag=0;//設定標記,a裡有大於b的則為1,沒有則為0
			int min_a=1000000;//記錄a數組裡最小的一個
			int min_a_flag=0;//記錄a數組裡最小的一個的座標
			int min=10000000;//假設有的話。用min來表示裡邊最小的一個
			int min_flag=0;//記錄min的座標
			for(int i=0;i<a.length;i++){
				
				if(a[i]>b[0]){//總是比較b的第一個
					flag=1;
					if(a[i]<min){
						min=a[i];
						min_flag=i;
					}
				}
				if(a[i]<min_a){
					min_a=a[i];
					min_a_flag=i;
				}
			}
			if(flag==0){//如果沒有大的
				//輸出a裡最小的 
				System.out.println(min_a);
				c[length-a.length]=min_a;
				//進行下一個遞迴(a、b陣列都減1個長度)
				int[] a_new=new int[a.length-1];
				int[] b_new=new int[a.length-1];
				for(int i=0;i<a.length-1;i++){//將a減少一個長度,去掉那個小的數
					if(i>=min_a_flag){
						a_new[i]=a[i+1];
					}else{
						a_new[i]=a[i];
					}
				}
				for(int i=1;i<a.length;i++){
					b_new[i-1]=b[i];
				}
				shuzu(a_new,b_new,c,length);
			}else{
				//輸出大的裡邊的最小的 
				System.out.println(min);

				c[length-a.length]=min;
				//進行下一個遞迴(a、b陣列都減1個長度)
				int[] a_new=new int[a.length-1];
				int[] b_new=new int[a.length-1];
				
				for(int i=0;i<a.length-1;i++){//將a減少一個長度,去掉那個小的數
					if(i>=min_flag){
						a_new[i]=a[i+1];
					}else{
						a_new[i]=a[i];
					}
				}
				for(int i=1;i<a.length;i++){
					b_new[i-1]=b[i];
				}
				shuzu(a_new,b_new,c,length);
			}
		}
	}