2014阿里校招题--研发算法(28题)

已知三个升序整数数组a[l], b[m]和c[n]。请在三个数组中各找一个元素,使得组成的三元组距离最小。三元组的距离定义是:假设a[i], b[j]和c[k]是一个三元组,那么距离为:
distance = max(|a[i] - b[j]|, |a[i] - c[k]|, |b[j] - c[k]|)

请设计一求最小三元组距离的最优算法,并分析时间复杂度。

思想:

1、首先申请两个长度为l + m + n 的数组 t 与 f    数组t用来存储排序后的三个数组  f用来存储当前t数组中的元素位于哪个原始数组中,时间复杂度O(l + m + n)

2、tf数组用来表示 找到三个来自不同数组的元素

3、当tf每次满足时,我们找出其中最大的元素与最小的元素,二者差就是其距离,此时将最小值对应的tf位置为false再继续寻找下一个不同元素

4、每次要记录的元素(左中右)状态是左边,与中间的元素都是同类型元素最右边的,右边元素是同类型元素最左边的

5、三元组距离等最右边的元素减去最左边的元素,然后再把最左边的元素的tf位置为false, 接着从最右边的元素的下一个继续开始执行。

时间复杂度为O(l + m + n)

示例图





















此方法如有错误,欢迎大家指正,共同学习。



下面程序是匆匆写的,没有进行优化,思想是这样的。 


int findMinDist(int a[], int l, int b[], int m, int c[], int n){
	int *target = new int[l + m + n];
	int *flag = new int[l + m + n]; //0表示a, 1表示b, 2表示c
	int f[3] = {false};
	//a[l] b[m] c[n]
	int ti = l + m + n - 1;
	int t = ti;
	//-----------------以下是对三个数组进行排序------------------//
	while(l && m && n){
		if(a[l - 1] >= b[m - 1] && a[l - 1] >= c[n - 1]){
			target[t] = a[l - 1]; flag[t] = 0; l--;
		}else if(b[m - 1] >= a[l - 1] && b[m - 1] >= c[n - 1]){
			target[t] = b[m - 1]; flag[t] = 1; m--;
		}else{
			target[t] = c[n - 1]; flag[t] = 2; n--;
		}
		t--;
	}
	while(m && n){
		if(b[m - 1] > c[n - 1]){
			target[t] = b[m - 1]; flag[t] = 1; m--;
		}else{
			target[t] = c[n - 1]; flag[t] = 2; n--;
		}
		t--;
	}
	while(n && l){
		if(a[l - 1] > c[n - 1]){
			target[t] = a[l - 1]; flag[t] = 0; l--;
		}else{
			target[t] = c[n - 1]; flag[t] = 2; n--;
		}
		t--;
	}
	while(l && m){
		if(a[l - 1] > b[m - 1]){
			target[t] = a[l - 1]; flag[t] = 0; l--;
		}else{
			target[t] = b[m - 1]; flag[t] = 1; m--;
		}
		t--;
	}

	while(l){target[t] = a[l - 1]; flag[t] = 0; l--; t--;}
	while(m){target[t] = b[m - 1]; flag[t] = 1; m--; t--;}
	while(n){target[t] = c[n - 1]; flag[t] = 2; n--; t--;}
	//-----------------------------------------------------------------//

	int i = 0, j = 0, k = 0; 
	int tmp = 0;
	int minV = INT_MAX;

	while(tmp <= ti){ //i,j,k用来标记三个来自不同数组的元素
		if(flag[tmp] == 0){
			i = tmp;
		}else if(flag[tmp] == 1){
			j = tmp;
		}else{
			k = tmp;
		}
		f[flag[tmp]] = true; //已经找到的不同元素标记为true
		if(f[0] && f[1] && f[2]){
			if(i > j && i > k){
				if(j < k){ //j k i
					minV = min(minV, target[i] - target[j]); f[1] = false;
				}else{ //k j i
					minV = min(minV, target[i] - target[k]); f[2] = false;
				}
			}else if(j > i && j > k){
				if(i < k){ // i k j
					minV = min(minV, target[j] - target[i]); f[0] = false;
				}else{ // k i j
					minV = min(minV, target[j] - target[k]); f[2] = false;
				}
			}else{
				if(i < j){ // i j k
					minV = min(minV, target[k] - target[i]); f[0] = false;
				}else{ // j i k
					minV = min(minV, target[k] - target[j]); f[1] = false;
				}
			}
		}
		tmp++;
	}

	return minV;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值