浙江工商大学oj iSTEP 1057 两数组最短距离 的 一种o(n+m)c语言解法

题目链接: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!!!!!!!!!!!!!!!!

 

 

如有哪有不足或更好的解决方法,请慷慨提出,感激不尽!!!

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值