一道阿里的内推编程测试题

博主今年研二,前几天舍友找实习投了阿里的内推,然后做了50分钟的测试题和一道编程题,测试题不用说,基本上就是智力题和性格测试,编程题限时30分钟,当时她没做出来,交卷后我俩讨论了很久,大概有了个结果,觉得可以把思路分享一下。

题目大致如下:
输入两个数字串
1.将数字串的某一位+1
2.将数字串的某一位-1
3.交换数字串中任意两个数字的位置
最终使得第一个数字串变成第二个数字串,请问最少需要多少次操作?

题意应该是将第一个数的各位数字通过交换位置、加减运算最终变成第二个数,求最小操作次数。

我们把这两个数字的各位存成两个数组
eg:
214
125
存成数组
a[]={2,1,4}
b[]={1,2,5}

题干给出的操作是三种,可以分为两类:交换、非交换。不论进行的是+运算还是-运算,操作次数都是|a[i]-b[i]|。要求最小操作次数,一定是先进行交换,再进行+-运算。
分析数组间元素的交换,是这道题重点。

a数列元素间需要进行交换时,一定是存在i,j (i≠j)∈[0,a.length),使得a[i] = b[j]。
当a[i] = b[i]时,a[i]元素达到平衡状态,此时还需要进行的操作为0,因此,a[i] ==b[i],是这道题的出口。

下面列出数组中交换可能存在的几种情况(按处理优先级):
(1)
a:1
b:1
需要进行n=0次交换,使得1个元素达到平衡状态;
(2)
a:1 2
b:2 1
需要进行n=1次交换,使得2个元素达到平衡状态;
(3)
a:2 1
b:3 2
需要进行n=1此操作,使得1个元素达到平衡状态。

这是我们最开始分析的三种情况,但马上发现不对,(3)状态之前还存在一种特殊情况,我用例子来说明:
a:9 5 7 8
b:5 7 8 5
此时{a,b}不存在(1)、(2)中所说的情况,但a中第二个元素5是应该与9交换还是与8进行交换?我们可以计算一下:
如果与9交换,此时总操作次数
n=1+1+1+4=7(包含+-操作)
如果与8进行交换, 此时总操作次数
n=1+1+4=6(包含+-操作)
由于交换位置不会导致数组所有元素和的大小,所以这里造成的n的不同与+-操作无关,而是因为在交换过程中出现了(2)情况,减少了一次操作。针对这种情况,我们提供一种解决方案,换一种思路考虑,在(3)中优先解决如下情况:
当a[i]是交换数(存在b[k]=a[i]),且存在j≠i,b[i]=a[j]。
此时优先交换a[i],在交换(3)中其他存在的还需要交换的元素。

当执行完以上需要交换的操作后,就可以最后进行 +-操作了。
最后附上我写的JAVA代码,供大家参考。这个代码我测试了一些用例,暂时没有发现什么错误,如果大家发现代码有什么情况没有考虑可以告诉我,或者还有什么更简单的思路或者更优化的代码结构可以相互交流。博主不是计算机专业,java基础不是很好,代码写得不好,大家不要怪哈~~

java代码:
public class Test {

	public static void main(String[] args) {
		
		int x = 214;
		int y = 125;
		int a[] = toArray(x);
		int b[] = toArray(y);		
		System.out.println(rec_exchange(a, b));		

	}
	
	public static int[] toArray(int x){
		
		String str = String.valueOf(x);
		int a[] = new int[str.length()];
		for(int i=0;i<a.length;i++){
			//a[i] = Integer.parseInt((String) str.subSequence(i, i+1));
			a[i] = Integer.parseInt(str.substring(i, i+1));
		}
		return a;
	}
	
	public static int rec_exchange(int[] a, int[] b) {
		
		int i;
		int j;
		int num=0;//次数
		
		if(a==null || b==null){
			return 0;
		}
		if(a.length != b.length){
			return -1;
		}
		
		//第(1)种情况
		for(i=0;i<a.length;i++){
			if(a[i]==b[i]){
				a = newArray(a,i);
				b = newArray(b,i);
				return num + rec_exchange(a, b);
			}			
		}
		
		//第(2)种情况
		for(i=0;i<a.length;i++){
			for(j=0;j<b.length;j++){
				if(i!=j && a[i]==b[j] && a[j]==b[i]){
					num++;
					a = newArray(a,j);
					a = newArray(a,i);
					b = newArray(b,j);
					b = newArray(b,i);
					return num + rec_exchange(a, b);
				}
			}
		}
		
		//第(3)种的优先情况
		for(i=0;i<a.length;i++){			
			for(j=0;j<b.length;j++){
				for(int z=0;z<b.length;z++){
					if(i!=j && i!=j && j!=z && a[i]==b[j] && a[j]==b[z]){
						num++;						
						a = exchangeSpace(a, i, j);
						a = newArray(a,j);
						b = newArray(b,j);
						return num + rec_exchange(a, b);
					}
				}
				
			}
		}
		
		//第3种的其他情况
		for(i=0;i<a.length;i++){			
			for(j=0;j<b.length;j++){
				if(a[i]==b[j]){
					num++;
					a = exchangeSpace(a, i, j);
					a = newArray(a,j);
					b = newArray(b,j);
					return num + rec_exchange(a, b);
				}								
			}
		}
		
		//+-运算
		for(i=0;i<a.length;i++){			
			int diff=0;
			diff = a[i]-b[i];
			if(diff>0){
				num += diff;
			}
			if(diff<0){
				num -= diff;
			}
		}				
		return num;
	}
	
	public static int[] exchangeSpace(int[] a,int i,int j){
		
		int t;
		t = a[i];
		a[i] = a[j];
		a[j] = t;
		return a;
	}
	
	public static int[] newArray(int a[], int i){
		
		if(a.length<=1){
			return null;
		}else{
	
			int[] arr = new int[a.length-1];
			int count=0;
			for(int j=0;j<a.length;j++){
				if(j!=i){
					arr[count]=a[j];
					count++;
				}
			}
			return arr;
		}
	}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值