【408DS算法题】进阶011-20年真题_三元组的最小距离

真题题目

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

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

(本文重点关注算法实现思路,不含具体答题表述)

分析实现

首先分析实现本题的中心——三元组的距离D。三元组的距离为三个元素中两两元素的距离之和,即 2 × ( 最大值 − 最小值 ) 2\times(最大值-最小值) 2×(最大值最小值)
故决定三元组距离大小的是处于边缘的元素,又因为三数组都是升序的,可以通过每次将三个数组中最小的元素“增大一点”(最小元素所在数组对应指针++),并不断记录下扫描过程中的最小距离。这样的策略来得到三元组的最小距离。

具体实现如下:

#include <vector>
#include <cmath>
#define INT_MAX 0x7fffffff

int distance(int a, int b, int c){
	return abs(a-b) + abs(b-c) + abs(c-a);
}
int minDistance(vector<int> a, vector<int> b, vector<int> c){
	int i=0, j=0, k=0;
	int minD = INT_MAX;	// 所有三元组的最小距离
	int d;				// 当前三元组的距离
	while(i<a.size() && j<b.size() && k<c.size() && minD>0){
		d = distance(a[i], b[j], c[k]);	// 计算当前三元组的距离
		if(d<minD)
			minD = d;
		// 三元组中最小的元素向后移动一位
		if(a[i]<=b[j] && a[i]<=c[k])
			i++;
		else if(b[j]<=a[i] && b[j]<=c[k])
			j++;
		else 
			k++;
	}
	return minD;
}

总结

以上就是通过定义三个指针,不断调整最小指针逐步进行扫描,以得出三数组构成三元组最小距离的过程。代码中使用了cmath头文件中的abs函数来计算绝对值。

本题的核心在于分析简化三元组的距离公式,根据简化后的公式可以相对顺利地得出优化后的解题方法。

此外(非重点),本篇代码还采用了一个优化的小技巧——尽量不在循环体内定义变量(变量d特地定义在了循环体之外),因为如果在循环中定义局部变量,每次循环迭代都会进行一次空间的分配和释放,多次重复的操作会使得代码性能有所降低。

  • 12
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值