当前位置: 首页 > news >正文

C语言之折中查找

题目描述

n个数(),这 n个数已按从大到小顺序存放在一个数组中,然后有 T次查询,每次输入一个数,要求用折半查找法找出该数在数组中第一次出现的位置。如果不在数组中输出 0

输入

第一行数组元素的个数 n

第二行 n个数组元素的值。(10 9 8 7 6 5 4 3 2 1).

第三行输入查询次数 T)。

往下有 T 行,每行输入一个需要查询的数字。

输出

查找的值在数组中的位置。

提示

注意:数组空间为 1000000 和 100000.

tips:使用 scanfprintf 会更快哦.

#include<stdio.h>
int main()
{int n;scanf("%d",&n);int a[n];int i;for(i=0;i<n;i++){scanf("%d",&a[i]);}int t;scanf("%d",&t);int b[t];for(i=0;i<t;i++){scanf("%d",&b[i]);}for(i=0;i<t;i++){int left=0,right=n-1;int first_pos=-1;//first_pos用来记录第一次出现位置的关键变量。而-1表示还没找到第一次出现位置。while(left<=right){int mid=left+(right-left)/2;if(b[i]==a[mid]){first_pos=mid;//记录找到的当前位置right=mid-1;//再往左找,看看是否有比第一次的中值位置还往前的}else if(b[i]<a[mid]){left=mid+1;}else if(b[i]>a[mid]){right=mid-1;}}if(first_pos!=-1){printf("%d\n",first_pos+1);}else{printf("0\n");}} return 0;
} 

问题一:为什么要使用first_pos=-1,来记录第一次出现位置?

因为题目要求用折半查找法找出该数在数组中第一次出现的位置。折半查找找到的值可能是任意一个匹配的位置,不一定是第一个。用标志变量来最后输出。如果不记录,即为下述 

if(a[mid]==b[i]){printf("%d\n",mid+1);break; 
}

这样输出的可能是中间的一个值。为了不让输出中间的值,则一定要定义一个变量来记录位置,如果在前面还能找到该值,则if语句成立,不断将变量的值更新,最后不成立的时候,即为第一次出现的位置,最后就可以输出了。而如果哪一个条件都不满足,最后first_pos=-1,不变,仍为初始值,既没有找到符合条件的位置,则输出0.

同时,因为题目有数组空间限制,所以如果遍历的话容易超时,此时定义一个标志变量才不会使数组溢出或时间超限。

综上所述,有个标志变量是最正确的选择。

问题二:为什么是 int mid=left+(right-left)/2;而不是mid=(left+right)/2;?

第一种mid定义会避免整数溢出,当left和right都很大时,如下述:

int left=1000000;
int right=1000000;
int mid2=(left+right)/2;//相加之后变成两倍,会溢出。
int mid1=left+(right-left)/2;//相减之后变成0,再加上left,值没有变得很大,所以不会导致值溢出。 

因此,以后碰到会出现数组溢出或者时间超限的时候就要考虑加法是否会变的特别大。

这种折中查找刚好不会隔开任何数,可以跳跃遍历所有可能正确的值,这正是这种方法的高效之处。正如上述十个数字,如果要查找8,mid=4,a[mid]=a[4]=6<8,所以会right=mid-1=3,之后mid=1;a[mid]=a[1]=9>8,向后查找,left=2,mid=2,此时中值的位置刚好是要找的数字。不会一直朝一个方向,而是根据需要找位置。

特别注意:最后输出的是位置,应该是下标加1. 

http://www.jsqmd.com/news/59995/

相关文章:

  • 【第七章:时间序列模型】3.时间序列实战:使用时序模型进行股票预测实战 - 实践
  • 罗克韦尔Micro850 PLC和欧姆龙NJ互通离不开Modbus工业物联网技术支撑
  • 一条不太寻常的路 —— AFO 退役记 -
  • Go 语言:类型别名 vs 新类型详解 - 若
  • pytest高级用法之mark
  • 20232320 2025-2026-1 《网络与系统攻防技术》实验八实验报告
  • 第一篇Scrum冲刺
  • Vibe Coding - 深度解读规范驱动制作(SDD):对 Kiro、spec-kit、Tessl 三大设备的剖析与实践
  • 第六篇SCrum冲刺
  • Hudi 文件格式分析
  • ai故事生成报告 - f
  • 落山基唬人队-冲刺总结
  • 深入解析:微信小程序通过关联公众号发送待办消息:实战指南
  • 团队作业4
  • 生命是一树花开
  • 深入解析:【5】理解GUID和Handle:解锁UEFI驱动和应用程序的钥匙
  • JavaSE--面向对象
  • 歌声转换SVC主流方法原理剖析4 — ReFlow-VAE-SVC
  • 重练算法(代码随想录版) day29 - 贪心part3
  • RocketMQ消息积压
  • spring的三级缓存及二三级缓存解决的问题 - 指南
  • 敏捷冲刺日志 - Day 5
  • 12月3日日记
  • 第五篇Scrum冲刺博客
  • 敏捷冲刺日志 - Day 6
  • 深入解析:Spring Kafka消费者被踢出组?CommitFailedException异常全面解析与解决方案
  • OWASP Java HTML 清理库曝出 XSS 漏洞:noscript 与 style 标签组合成隐患
  • 敏捷冲刺日志 - Day 4
  • 计算机视觉黄金时代的回顾与展望
  • homebrew运行机制