数据基本操作——查找

查找(searching)
先上一道阿里的面试题吧
题意是这样描述的,给定一个m行n列的整数矩阵(如图),每行从左到右,每列从上到下都是有序的。判断一个整数k是否在矩阵中出现的最优算法,在最坏的情况下的时间复杂度
1 5 7 9
4 6 10 15
8 11 12 19
14 16 18 21
A–O(mXn)
B–O(m+n)
C–O(log(mXn))
D–O(log(m+n))
只有第一题有点思路,这学期才开始数据结构的学习。在局部有序中进行查找,同样是可以用二分查找法的。为了问题的简化,不妨先假设n=m,那么这个矩阵就是n阶方阵。从主对角线上的元素开始进行二分查找,考虑最坏情况耗时为:log(n)。然后对左下角和右上角的两个n/2阶方阵分别又从主对角线上的元素开始进行二分查找,重复步骤到最后。每一次把矩阵分为了1,2,4,8,2^i个,运用了递归的思想。故时间复杂度应为:T(n)=1*log(n/1)+2log(n/2)+4log(n/4)+2^(i)log(n/2^(i))+…+;观察前几项可以把C,D选项直接排除。对这个级数求和大致可以得到O(2n),从而选项B:O(n+m)是正确的。(其实大O表示法在这里不是严密的,我们也可以选A,因为由大O的定义O(m*n)包含了O(m+n),虽然这并不符合题意)

分类

  • 静态查找
    1:顺序查找
//数组data,0到length-1都存有数据
for(i=0;i<length;i++)
  if(key==data[i]) return i;
return 0;
//数组data,1到length中存有数据
for(i=length;i>0&&key!=data[i];i--);
return i;
//设置哨兵,有唯一出口和单个判断条件
data[0]=key;
for(i=length;key!=data[i];i--);
return i;

2:二分查找
假设树的深度depth是从1开始的,则查找判定树的depth= logN or logN +1
ASL:成功查找每个元素所需要的平均判定次数

//注意data数组中的数据是从1开始存放的
left=1;
right=length;
Notfind=-1;
while(left<right+1)//left<=right,最好不要带有“=”号
{
  mid=(left+right)/2;
  if(data[mid]<key) left=mid+1;
  else if(data[mid]>key) right=mid-1;
       else  return mid;
  }
return Notfind;
 //在这个代码段中如果每次更新left和right用的不是mid+1和mid+1,则当查找的元素不再有序的序列中,就会进入死循环。**注意!在其他程序中的判定条件和更新边界的方法是不同,但是二分的思想是相同的,自己可以写出正确的代码来**

3.黄金分割查找

#include <math.h>
//_CRTIMP double __cdecl ceil (double);向上取整(天花板)
//_CRTIMP double __cdecl floor (double);向下取整(地板)
#define cut 0.618
left=1;
right=length;
Notfind=-1;
while(left<right+1)
{
  mid=(int)(left+cut*(right-left));//mid必须是整型
  //mid=floor(left+cut*(right-left));
  if(data[mid]<key) right=mid-1;
  else if(data[mid]>key) left=mid+1;
  else return mid;
}
return Notfind;
  • 动态查找
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值