【C语言.oj刷题】有序#整型矩阵元素查找##{思路+C源码}

 

目录

 题目信息

题目分析:

法一:

遍历二维数组(低效)

思路

源码

 局限性

 法二:

对每一行二分查找(有所提效)

思路

 源码

局限性

法三:

利用一切有利条件使用二分查找

思路

源码

局限性

 二分查找源码:


 

 题目信息

        有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。

要求:时间复杂度小于O(N);


题目分析:

        这道题是什么情况呢?其实就是说,有下面的这样一个满足要求的矩阵:

 

 干脆  , 更直观一点:


         也就是,在这样的矩阵(每一行从左到右递增,每一列从上到下递增)中查找一个特定的元素。

        如果找到,确定它的位置;如果找不到,输出  -1 ;

法一:

 

遍历二维数组(低效)

 

思路

        我们首先最容易想到的,也是最简单的方法,就是遍历数组,一个一个去试一试,看看能不能找到。

源码


#define ROW 5
#define COL 5int main()
{int key;scanf("%d",&key);char arr[ROW][COL] = {{1,2,3,4,5},{4,5,6,7,8},{5,6,7,8,10},{10,11,12,13,14},{15,16,17,18,19}};int i = 0;for(i = 0;i < ROW;i++){int j = 0;for(j = 0;j < COL;j++){if(key ==arr[i][j]){printf("找到了,在%d行%d列\n",i,j);break;}}}return 0;
}

 

         

         对照一下结果,代码是正确的。

 局限性

 

        经过计算,遍历算法的时间复杂度为O(N^2)

         虽然遍历算法思路简单易想,这样的时间复杂度太大,不再符合题目要求。

 法二:

 

对每一行二分查找(有所提效)

 

思路

        由于数组的每一行都是有序的,这样就满足了二分查找的使用条件,所以可以直接对每一行二分查找:

        直观一点:

 源码


#define ROW 5
#define COL 5
#include<stdio.h>
#include<string.h>
int bi_search(int arr[ROW],int sz,int key)
{int f = 0;int left = 0;int right = sz-1;int mid = (left + right)/2;while(left<=right){   mid = (left + right)/2;if(arr[mid] > key){right = mid - 1;}else if(arr[mid] < key){left = mid + 1;}else if(arr[mid] == key){f = 1;return mid;}}if(f == 0){return -1;}
}
int main()
{int key;scanf("%d",&key);int arr[ROW][COL] = {{1,2,3,4,5},{4,5,6,7,8},{5,6,7,8,10},{10,11,12,13,14},{15,16,17,18,19}};int i = 0;int f = 0;for(i = 0;i < ROW;i++){int ret = bi_search(arr[i],COL,key);if(ret != -1){f = 1;printf("找到了,在%d行%d列\n",i,ret);}}if(f == 0){printf("找不到");}return 0;
}

         在实际动手写代码时,我也遇到了一些问题,比如刚开始把打印找不到放在循环内,结果出现了这样的结果:

         这就挺尴尬的,解决办法是引入判断变量f,然后先假设找不到f初始化为0;如果找到,f置为1,如果直到循环完毕,f都没有被置为1,则就是整个数组都没有key;

局限性

        经计算,对每一行进行二分查找算法的时间复杂度为O(N log2(N))

虽然速度有所提升,但是效率仍然达不到题目要求。 

 

法三:

 

利用一切有利条件使用二分查找

 

思路

         我们可以先对行进行二分查找

        假设找9,在比9大的前一个元素前停下,由于行列都是从小到大递增的,所以可以断定后两行没有要找的元素9

 

  对行二分查找

 

 后两行没有9

 

 

 

 接下来对行进行二分查找,但是我们发现所有的行都小于要查找的key,所以接下来只能对剩下的3行分别二分查找。

 

 

 在这种n = 5 ,的情况下,我们发现时间复杂度并没有降低多少,我们分析一下:

        每一行二分,需要5次;

        而先列,进行排除;再行,需要4次;

但是在一般情况下,n可能很大,可能是100000,甚至更大,在这种情况下,程序有很大程度的提效。

 

 

 时间复杂度N的趋势:

 

源码

       我在写这个代码的时候遇到了一些问题,在对第一列进行二分查找后,在不再次遍历数组的情况下(不再增加时间复杂度),没有办法定位到合适的位置(在这个位置上,数组的后一个元素的大小大于key,数组前一个元素大小小于key,),你可以想一想,私信我交流。

局限性

         假设第k个找到合适位置,需要进行两次二分查找,时间复杂度是(log2(N)),剩下每一行都可能会出现key;

       

        但在此处,我选择对排除后的每一行进行二分查找,时间复杂度为(k*log2(k));

则时间复杂度的表达式为:

        T = log2(N)+   k*log2(k)  (k < N)

         最差情况,k == N,时间复杂度O(N* ( log2 (N) ) );

         最优解:k == 0,时间复杂度O(1);

        其实,我们可以设计更复杂的算法,这样可以进一步提高效率;

         提供一种思路:沿着对角线遍历n*n的矩阵,找到合适的停留点,这样又可以排除一部分可能:

 

         如果你可以巧妙利用题目信息,那么,即使有时间限制,oj题目对你来说一定不在话下!

         加油吧!


 

 二分查找源码:

int bi_search(int arr[ROW],int sz,int key)//参数分别是:要查找的行,数组元素的个数,要查找的对象
{int f = 0;int left = 0;int right = sz-1;int mid = (left + right)/2;while(left<=right){   mid = (left + right)/2;if(arr[mid] > key){right = mid - 1;}else if(arr[mid] < key){left = mid + 1;}else if(arr[mid] == key){f = 1;return 1;//如果找到,返回1}}if(f == 0){return -1;//如果找不到,返回-1}
}

完~

 未经作者同意禁止转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/195528.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性表--链表-1

文章目录 主要内容一.链表练习题1.设计一个递归算法&#xff0c;删除不带头结点的单链表 L 中所有值为 X 的结点代码如下&#xff08;示例&#xff09;: 2.设 L为带头结点的单链表&#xff0c;编写算法实现从尾到头反向输出每个结点的值代码如下&#xff08;示例&#xff09;: …

git常用命令和参数有哪些?【git看这一篇就够了】

文章目录 前言常用命令有哪些git速查表奉上常用参数后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;git操作相关 &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出…

Linux应用开发基础知识——输入系统应用编程(八)

前言&#xff1a; 触摸屏分为电阻屏、电容屏。电阻屏结构简单&#xff0c;在以前很流行&#xff1b;电容屏支持多点触摸&#xff0c;现在的手机基本都是使用电容屏。我们应当注意的是LCD、触摸屏不是一回事&#xff0c;LCD 是输出设备&#xff0c;触摸屏是输入设备。制作触摸屏…

Linux下快速确定目标服务器支持哪些协议和密码套件

实现原理是利用TLS协议的特点和握手过程来进行测试和解析响应来确定目标服务器支持哪些TLS协议和密码套件。 在TLS握手过程中&#xff0c;客户端和服务器会协商并使用相同的TLS协议版本和密码套件来进行通信。通过发送特定的握手请求并分析响应&#xff0c;可以确定目标服务器…

入股合作协议要不要写章程

公司章程&#xff0c;是注册公司的基本文件&#xff0c;也公司必备的规定公司组织及活动基本规则的书面文件&#xff0c;是公司成立的必不可少的基础&#xff0c;也是公司赖以生存的灵魂。那么&#xff0c;这次要和大家讨论的是有关于入股合作协议要不要写章程的问题了。 入股合…

Spring cloud - Hystrix服务限流、熔断及降级

Hystrix的作用 Hystrix的主要作用是在微服务环境下防止服务雪崩&#xff0c;确保服务弹性及可用性。 具体来说&#xff0c;Hystrix可以实现&#xff1a; 服务降级&#xff1a;通过fallback实现服务不可达情况下的服务降级作用。熔断&#xff1a;服务不可达的情况下在设定时间…

Python---练习:封装一个函数,用于生成指定长度的验证码

练习涉及相关链接&#xff1a;Python---练习&#xff1a;编写一段Python代码&#xff0c;生成一个随机的4位验证码-CSDN博客 Python----函数中的说明文档-CSDN博客Python---return返回值-CSDN博客 代码&#xff1a; # 定义一个generate_code()函数 def generate_code(num): …

〖大前端 - 基础入门三大核心之JS篇㊳〗- DOM访问元素节点

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…

基于一致性算法的微电网分布式控制MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 本模型主要是基于一致性理论的自适应虚拟阻抗、二次电压补偿以及二次频率补偿&#xff0c;实现功率均分&#xff0c;保证电压以及频率稳定性。 一致性算法 分布式一致性控制主要分为两类&#xff1a;协调同…

探索无限可能:APITable免费开源多维表格与可视化数据库远程访问的魅力

APITable免费开源的多维表格与可视化数据库公网远程访问 文章目录 APITable免费开源的多维表格与可视化数据库公网远程访问前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c…

JAVA多线程(5)

JAVA多线程(5) 线程安全问题概述 卖票问题分析 单窗口卖票 一个窗口(单线程)卖100张票没有问题 单线程程序是不会出现线程安全问题的 多个窗口卖不同的票 3个窗口一起卖票,卖的票不同,也不会出现问题 多线程程序,没有访问共享数据,不会产生问题 多个窗口卖相同的票 3个窗口…

C语言:动态内存管理

目录 为什么存在动态内存分配 动态内存函数 malloc和free 示例 calloc 示例 realloc 示例 常见的动态内存错误 对NULL指针的解引用操作 对动态开辟的空间进行越界访问 对于非动态开辟内存使用free释放 使用free释放一块动态开辟内存的一部分 对同一块内存多次释…