题目链接:iSTEP | 两数组最短距离
此为 浙江工商大学oj编程实训参考题库(题号列表)-CSDN博客 系列的一篇文章。
===================================================================================================
题目 两数组最短距离
描述
已知元素从小到大排列的两个数组x[]和y[],请写出一个程序算出两个数组彼此之间差的绝对值中最小的一个,这叫做数组的距离。
输入
第一行为两个整数m, n(1≤m, n≤1000),分别代表数组f[], g[]的长度。 第二行有m个元素,为数组f[]。 第三行有n个元素,为数组g[]。
输出
数组的最短距离。
输入样例 1
5 5 1 2 3 4 5 6 7 8 9 10
输出样例 1
1
===================================================================================================
解题挫见:能把题目做出来当然很好的,但对于新手写的代码来说往往会有很大的优化空间,我们称优化的过程叫做优化算法。可一些优化过程并不是有系统型的算法,我称这些优化过程为技巧。
在这道题中我们很容易想出o(n^2)的算法:暴力全部数据都相减一边然后取求最小值。(o()成为时间复杂度,可以参考这篇文章时间复杂度_o(m+n)-CSDN博客)
但是这道题目有很大的优化空间,完全可以优化成o(n+m)。
下面提供两种思路
1.以f[0]为基准不断i++,直至f(i)介于g(j)与g(j+1)之间。
将f(i)分别与g(j)与g(j+1)作差然后取最小值,然后在与现存的最小值作比较,留下最小的那个。
继续i++,执行上面的两步直至j+1或i碰到n或m。
(还要考虑f(max)比g(0)小和g(max)比f(0)小的两种特例)
2.(由cc学长想出)直接f(0)与i(0)相减,那方小了就进一位,如f(0)小于g(0),那么f(0)进一位再与g(0)相减继续比大小。
在此过程中一直记录比较 差的大小并保留最小值。
知识点:数据处理,技巧
以下为通过代码以及一些详细的注释(用c语言书写):(以第一种方式书写)
//
// Created by Mrlaolu on 2023/10/13.
//
#include "stdio.h"
int main()
{
int n,m,f[1020],g[1020],min = (unsigned int)(-1) >> 1; //n为f数组大小,m为g数组大小,min为最小值
scanf("%d%d",&n,&m);
for (int i = 0; i < n; ++i)
{
scanf("%d",&f[i]);
}
for (int i = 0; i < m; ++i)
{
scanf("%d",&g[i]);
}
for (int i = 0,j = 0; i < n || j + 1 == m; ++i)
{
if(g[j] < f[i] && g[j+1] > f[i]) //以f[i]为基点,一直找到 g[j+1] > f[i] > g[j] 的值 然后做差取最小值
{
int reg = (f[i] - g[i] < g[j + 1] - f[i]) ? (f[i] - g[i]) : (g[j + 1] - f[i]);
if( reg < min )
{
min = reg;
}
}
else if(i == n || g[j] > f[i]) //到了f[n]还比g[j]小 那就记录这个值 这个值是所有f[]中的数与g[j]作差最小的值 然后结束搜索
{
int reg = g[j] - f[i];
if( reg < min )
{
min = reg;
}
}
else if(j + 1 == m - 1 || g[j + 1] < f[i]) //到了f[n]还比g[j]大 那就记录这个值 这个值是所有g[]中的数f[i]作差与最小的值 然后结束搜索
{
int reg = f[i] - g[j + 1] ;
if( reg < min )
{
min = reg;
}
--i;
++j;
}
else if(g[j + 1] == f[i] || g[j] == f[i]) //一旦两个数组中有相等 那么直接最小值为0 后面的数就不用看了
{
min = 0;
break;
}
}
printf("%d",min);
}
!!!!!!!!!!!!!!!!!!!仅参考思路,严禁直接ctrl+c!!!!!!!!!!!!!!!!
如有哪有不足或更好的解决方法,请慷慨提出,感激不尽!!!