【2020年408统考真题】三元组的最小距离

· 前言

这个模拟放只是我首次做这道题目时候想到的思路,后来对了下答案,方向大体上正确,但是没有更深、更进一步考虑,这里就当做引出答案解法的引子记录着了。

· 题目内容

定义三元组(a,b,c)(a,b,c均为整数)的距离D=|a-b|+|b-c|+|c-a|。给定3个非空整数集合S1、S2和S3,按升序分别存储在3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)(a∈S1,b∈S2,c∈S3)中的最小距离。例如S1={-1,0,9},S2={-25,-10,10,11},S3={2,9,17,30,41},则最小距离为 2,相应的三元组为(9.10.9)。要求:
1) 给出算法的基本设计思想。
2) 根据设计思想,采用C语言或 C++语言描述算法,关键之处给出注释,
3) 说明你所设计算法的时间复杂度和空间复杂度。

· 基本思想

1.暴力破解

直接三重循环,每次计算距离并且更新D的值为最小者。最后输出D即可

时间复杂度:三重循环,O(n³)

空间复杂度:O(1)

2.模拟法(已过时)
分析:

暴力破解主要的时间消耗在枚举所有可能的三元组上,我们可以试着想一下,能否找到一个办法,尽量减少枚举次数或者减少循环层数,来降低时间复杂度。

根据题目给出的距离的定义,我们可以发现,如果我们固定了a,b的值(或者说a,b在数轴上位置),最后D只跟c的取值有关系。不失一般性,我们假定a<b(对a=b的情况也可以用相同的思路去分析),每次固定a,b的值,把c看作动点来考察c取值变化与距离D的关系:

当c<a时,D1=a-c+b-c+b-a=-2c+2b;当a≤c≤b时,D2=b-a+b-c+c-a=2(b-a),是与c无关的常数;当c>b时,D3=b-a+c-b+c-a=2c-2a。并且c<a时,D1=2(b-c)>2(b-a)=D2;c>b时D3=2(c-a)>2(b-a)=D2,即当c介于a,b之间时D取到极小值。

 c的取值离散,分以下几种情况:

①c的取值有落在(a,b)之间的点,此时Dmin=2|a-b|;

②c的取值全落在a左侧,此时D=2b-2c,当c取最大值时D取到极小值

③c的取值全落在b右侧,此时D=2b-2c

④c的取值有落在a左侧,有落在b右侧的,但是没有落在a,b之间的,此时要比较最靠近a和b的两个取值对应的D大小

这样,只需要一个二重循环枚举a,b即可。并且在枚举a,b时,遇到重复的元素可以直接跳过,进一步优化运行时间(但不会改变时间复杂度)

时间复杂度

枚举a,b需要一个二重循环,枚举c的时间复杂度最好为O(1),最差为O(N)。总体时间复杂度O(N²)~O(N³)

3.模拟法的再优化(这才是真正的模拟法)

看了一下答案的解法,发现我还是想的浅了。答案考虑到了更具有一般性的情况。重新看一下上面提到的几种情况,发现每次D只跟距离最远的两个点间的距离有关系,也就是a,b,c中的最大值和最小值间的距离有关。题目要求D最小,而且S1,S2,S3已经升序排列了,每次只需要移动值最小的元素,计算D然后考察D和Dmin之间的关系就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值