求排列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);
			}
		}
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值