数据结构_算法实现顺序表相关问题_14

一、问题描述:

定义三元组(a,b,c)(a,b,c均为整数)的距离D = |a - b| + |b - c| + |c - a|。给定3个飞控证书集合S1、S2和S3,按升序分别存储在3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)(a ∈ \in S1,b ∈ \in S2,c ∈ \in S3)中的最小距离。例如S1 = {-1,0,9},S2 = {-25,-10,10,11},S3 = {2,9,17,30,41},则最小距离为2,相应的三元组为(9,10,9)。要求:

  • 给出算法的基本设计思想。
  • 根据设计思想,采用C语言或C++语言描述算法,关键之处给出注释。
  • 说明你所设计算法的时间复杂度和空间复杂度。

二、算法思想:

分析:由D = |a - b| + |b - c| + |c - a| >= 0由如下结论。

  • 当a = b = c时,距离最小。
  • 其余情况。不失一般性,假设a <= b <= c,观察下面的数轴:
    图1
    L1 = |a - b|
    L2 = |b - c|
    L3 = |c - a|
    D = |a - b| + |b - c| + |c - a| = L1 + L2 + L3 = 2L3
  • 由D的表达式可知,事实上决定D大小的关键是a和c之间的距离,于是问题就可以简化为每次固定c找一个a,使得L3 = |c - a|最小。
  • 使用Dmin记录所有已处理的三元组的最小距离,初值为一个足够大的整数。
  • 集合S1、S2和S3分别保存在数组A、B、C中。数组的下标变量i = j = k = 0,当i<|S1|、j<|S2|且k<|S3|时(|S|表示集合S中的元素个数),循环执行下面的步骤:
    – 计算(A[i],B[j],C[k])的距离D;(计算D)
    – 若D<Dmin,则Dmin = D;(更新D)
    – 将A[i],B[j],C[k]中的最小值的下标+1;(对照分析:最小值为a,最大值为c,这里c不变而更新a,试图寻找更小的距离D)
    – 输出Dmin,结束。

三、算法代码:

#define INT_MAX 0X7fffffff
int abs_(int a)//计算绝对值
{
	if(a < 0)
		return -a;
	else
		return a;
	bool xls_min(int a,int b,int c)//a是否是三个数中的最小值
	{
		if(a <= b && a <= c)
			return true;
		return false;
	}
	int findMinofTrip(int A[],int n, int B[],int m,int C[],int p)
	//D_min用于记录三元组的最小距离,初值赋为INT_MAX
	{
		int i = 0,j = 0,D_min = INT_MAX,D;
		while(i < n && j < m && k < p && D_min > 0)
		{
			D = abs_(A[i] - B[j]) + abs_(B[j] - C[k]) + abs_(C[k] - A[i]);//计算D
			if(D < D_min)//更新D
				D_min = D;
			if(xls_min(A[i],B[j],C[k]))//更新a
				i++;
			else
			{
				if(xls_min(B[j],C[k],A[i]))
					j++;
				else
					k++;
			}
		}
		return D_min;
	}
}

三、算法复杂度:

设n = (|S1| + |S2| + |S3|)

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸭舌和鸭心我都要

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值