C语言(CED)查找最接近的元素(分治法/二分查找):在一个非降序列中,查找与给定值最接近的元素。(递归实现)

本文介绍了一种使用二分查找算法解决查找最接近元素问题的方法。通过递归方式,在非降序序列中找到与指定值最接近的数值。文章详细解释了二分查找的实现过程,并提供了一个完整的C语言代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(请先看置顶博文)本博打开方式,请详读_liO_Oil的博客-优快云博客_怎么把androidstudio卸载干净

一、题目大意

查找最接近的元素(分治法/二分查找):在一个非降序列中,查找与给定值最接近的元素。

[输入]

第一行包含一个整数n,为非降序列长度。

第二行包含n个整数,为非降序列各元素。

第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。

接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间

[输出]

m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个

input:

3

2 5 8

2

10

5

output:

8

5

二、主要思想

       我认为这道题考察的知识点有两个:一个是递归,另一个是二分查找。这个二分查找和通常的二分查找不一样,题目要求查找最接近的,所以这就给题目求解带来了很大的难度。我在写程序时,先在纸上模拟,用到了很多的ifelse判断语句,对可能出现的各种情况进行细分,最后实现了一个finder()函数,用于在递增数列中查找与要查找的数字最近的数字。

       关于二分

在写代码的时候遇到一个问题,就是关于long long的使用问题:

1、long long定义时,如果还用scanf()函数输入,编译器不报错,但是输入的数字完全改变。

针对这个问题,我也找到了相应的解决办法,请看这篇文章:C语言(CED)与long long相关的知识_liO_Oil的博客-优快云博客

三、具体实现

#include<stdio.h>
#include<stdlib.h>
int a[1000];//存放升序排列的一列数字
int b[1000];//存放要找的数字
int m;//输入要查找的数的个数
long long finder(int mx, int mn, int mid, int j)//
{//第一步区分查找的这个数是否在开区间内
	if (b[j] <= a[mn] || b[j] >= a[mx])//不在
	{
		//对内部进行细分,到底是比最小的还小,还是比最大的还大
		if (b[j] <= a[mn])  //比最小的还小
			printf("%d\n", a[mn]);
		else//比最大的还大
			printf("%d\n", a[mx]);
	}
	else//位于最小的数字和最大的数字之间
	{
		//根据mid来分,比mid大还是比mid小,还是和mid相等
		if (a[mn]<b[j] && b[j]<a[mid])//比mid小
		{
			if (mid - mn != 1)
			{
				mx = mid - 1;//将mx替换为mid
				mid = (mn + mx) / 2;//重新计算mid下标
				finder(mx, mn, mid, j);
			}
			else
			{
				if (a[mid] - b[j]>b[j] - a[mn])//比较距离
					printf("%d\n", a[mn]);
				else if (a[mid] - b[j]<b[j] - a[mn])
					printf("%d\n", a[mid]);
				else
					printf("%d %d\n", a[mn], a[mid]);
			}

		}
		else if (a[mid]<b[j] && b[j]<a[mx])//比mid大
		{

			if (mx - mid != 1)
			{
				mn = mid;//重新计算mn
				mid = (mn + mx) / 2;//重新计算mid下标
				finder(mx, mn, mid, j);
			}
			else
			{
				if (b[j] - a[mid]>a[mx] - b[j])
					printf("%d\n", a[mx]);
				else if (b[j] - a[mid]<a[mx] - b[j])
					printf("%d\n", a[mid]);
				else
					printf("%d %d\n", a[mid], a[mx]);
			}
		}
		else//和mid相等
			printf("%d\n", b[j]);
	}
	return 0;
}
int main()
{
	int j = 0;//用作函数循环的
	int n;//输入非降序序列的长度
	scanf("%d", &n);
	for (int i = 0; i<n; i++) //循环输入n个数字
		scanf("%d", &a[i]);
	scanf("%d", &m);    //输入要查询的数字个数
	for (int i = 0; i<m; i++) //循环输入要查找的数,存在b[i]中
		scanf("%d", &b[i]);
	int mx = n - 1, mn = 0;
	int mid = (mx + mn) / 2;
	for (j = 0; j<m; j++)//循环调用函数,把b[j]中存储的所有要找的数字找完
		finder(mx, mn, mid, j);
	system("pause");
	return 0;

}

在写完这个程序后,我用大量的数据,科学的测试方法(边缘测试)进行测试,结果是没有发现问题,如果大家在测试过程中发现问题,请及时留言,欢迎!

[root@dljycs-rancher1 categraf-v0.4.3-linux-amd64]# ./categraf --test --inputs prometheus 2025/03/10 15:00:18 main.go:150: I! runner.binarydir: /data/categraf-v0.4.3-linux-amd64 2025/03/10 15:00:18 main.go:151: I! runner.hostname: dljycs-rancher1 2025/03/10 15:00:18 main.go:152: I! runner.fd_limits: (soft=65536, hard=65536) 2025/03/10 15:00:18 main.go:153: I! runner.vm_limits: (soft=unlimited, hard=unlimited) 2025/03/10 15:00:18 provider_manager.go:60: I! use input provider: [local] 2025/03/10 15:00:18 ibex_agent.go:19: I! ibex agent disabled! 2025/03/10 15:00:18 agent.go:38: I! agent starting 2025/03/10 15:00:18 agent.go:46: I! [*agent.MetricsAgent] started 2025/03/10 15:00:18 prometheus_agent.go:27: I! prometheus scraping started! 2025/03/10 15:00:18 agent.go:46: I! [*agent.PrometheusAgent] started 2025/03/10 15:00:18 agent.go:49: I! agent started ts=2025-03-10T07:00:18.831Z caller=web.go:559 level=info component=web msg="Start listening for connections" address=127.0.0.1:0 ts=2025-03-10T07:00:18.831Z caller=prometheus.go:843 level=info msg="Starting WAL storage ..." ts=2025-03-10T07:00:18.831Z caller=dir_locker.go:77 level=warn msg="A lockfile from a previous execution already existed. It was repla ced" file=/data/categraf-v0.4.3-linux-amd64/data-agent/lockts=2025-03-10T07:00:18.831Z caller=prometheus.go:726 level=info msg="Stopping scrape discovery manager..." ts=2025-03-10T07:00:18.831Z caller=prometheus.go:740 level=info msg="Stopping notify discovery manager..." ts=2025-03-10T07:00:18.831Z caller=prometheus.go:762 level=info msg="Stopping scrape manager..." ts=2025-03-10T07:00:18.831Z caller=prometheus.go:736 level=info msg="Notify discovery manager stopped" ts=2025-03-10T07:00:18.832Z caller=notifier.go:608 level=info component=notifier msg="Stopping notification manager..." ts=2025-03-10T07:00:18.832Z caller=prometheus.go:918 level=info msg="Notifier manager stopped" ts=2025-03-10T07:00:18.832Z caller=prometheus.go:722 level=info msg="Scrape discovery manager stopped" ts=2025-03-10T07:00:18.832Z caller=tls_config.go:313 level=info component=web msg="Listening on" address=127.0.0.1:35523 ts=2025-03-10T07:00:18.832Z caller=tls_config.go:316 level=info component=web msg="TLS is disabled." http2=false address=127.0.0.1:355 23ts=2025-03-10T07:00:18.832Z caller=prometheus.go:756 level=info msg="Scrape manager stopped" ts=2025-03-10T07:00:18.832Z caller=prometheus.go:928 level=error err="opening storage failed lock DB directory: resource temporarily u navailable"
最新发布
03-11
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

liO_Oil

打赏我,开启隐藏模式。

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

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

打赏作者

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

抵扣说明:

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

余额充值