• 【杨氏矩阵】



    前言

    大家好,我是熊猫,今天要和大家一起学习的是在杨氏矩阵中寻找数字的问题。


    一、题目描述

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

    通过题目描述我们可以得知该矩阵为有序的,每一行、每一列都是从小到大排列的,要在这个矩阵中找数字。
    我想很多人看到这里的第一反应就是二分查找,二分查找虽然同样可以解决问题,不过效率并不是最高的,下面我们会介绍包括二分查找在内的两种方法,希望可以为大家带来不同的思路。


    二、题目解析

    (一)解法1 – 二分查找

    二分查找就是用两个下标 left ,right(也可以直接使用指针)一个在最左边一个在最右边,再有一个变量mid 来存放他们两个的中间值,并和我们的目标值进行比较,
    相等就结束循环,
    如果小于目标值,就把左边的下标移向中间值的左边一位 left = mid + 1;
    如果大于目标值,就把右边的下标移向中间值的左边一位 right = mid - 1;
    之后要比较left<= right,若果left在right的右边就说明目标值不存在。
    每一行都要进行一次。

    在这里插入图片描述

    代码如下(示例):

    #include
    #define ROW 4
    #define COL 4
    int Find(const int arr[ROW][COL],const int row,const  int col,const  int aim) {
    	if (aim<arr[0][0] || aim>arr[row - 1][col - 1])//判断是否超过范围
    		return 0;
    	for (int i = 0; i < row; i++){
    		int left = 0;
    		int right = col - 1;
    		while (left <= right) {
    			int mid = (left + right) / 2;
    			if (aim == arr[i][mid])
    				return 1;
    			else if (aim < arr[i][mid])
    				right = mid - 1;
    			else
    				left = mid + 1;
    		}
    	}
    	return 0;
    }
    
    int main() {
    	int n = 0;
    	while(1){
    		puts("请输入目标数字:");
    		scanf("%d", &n);
    		int arr[ROW][COL] = { 0 };
    		for (int i = 0; i < ROW; i++){
    			for (int j = 0; j < COL; j++) {
    				arr[i][j] = i + j;  //设置数组元素,这里为 0~6
    				printf("%d ", arr[i][j]);
    			}
    			printf("\n");
    		}
    		if (Find(arr, ROW, COL, n))
    			printf("存在\n");
    		else
    			printf("不存在\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    (二)解法2 – Step-wise线性搜索解法

    这里我们来认识一种很巧妙的方法,我们从右上角开始判断,
    相等就结束,
    如果这个数字小于目标数字就往左移动一格(列数减一),
    如果这个数字大于目标数字就往下移动一格(行数加一),
    如果找到最后都没有目标值就结束。
    也可以从左下角往右上角进行判断;
    这里之所以不使用左上角的值是因为:它是最小值,当目标值比它小的时候当然就可以直接结束,但是当目标值比它大的时候,不能确定是应该往左移动还是往下移动,这会增加判断的难度。

    在这里插入图片描述

    代码如下(示例):

    #include
    #define ROW 4
    #define COL 4
    int Find(const int arr[ROW][COL],const int row,const  int col,const  int aim) {
    	if (aim<arr[0][0] || aim>arr[row-1][col-1])
    		return 0;
    	int i = 0;
    	int j = col - 1;
    	while (i <= row-1 && j >= 0) {//从右上角移动到左下角
    		if (aim == arr[i][j])
    			return 1;
    		else
    			if (aim > arr[i][j])
    				i++;
    			else
    				j--;
    	}
    	return 0;
    }
    
    int main() {
    	int n = 0;
    	while (1) {
    		puts("请输入目标数字:");
    		scanf("%d", &n);
    		int arr[ROW][COL] = { 0 };
    		for (int i = 0; i < ROW; i++) {
    			for (int j = 0; j < COL; j++) {
    				arr[i][j] = i + j;
    				printf("%d ", arr[i][j]);
    			}
    			printf("\n");
    		}
    		if (Find(arr, ROW, COL, n))
    			printf("存在\n");
    		else
    			printf("不存在\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    总结

    以上就是熊猫对这个题目的理解,本题的解法有很多,如果大家还有其他好的做法欢迎在评论区留言,在此感谢大家对的支持,这是熊猫持续更新的巨大推进力!

  • 相关阅读:
    win10 本地通过docker提供kafka服务
    华为云云耀云服务器L实例评测|测试CentOS的网络配置和访问控制
    MySQL必知必会_第三、四、五、六章知识总结
    攻防世界-WEB-ics-05
    问题记录v(●‘◡‘●)v
    小程序Springboot基层慢性病信息管理系统毕业设计-附源码221550
    2022年最新广西道路运输安全员真题题库及答案
    信息化与信息系统5
    046:mapboxGL加载天地图路网图+标记(wmts方式)
    风丘电动汽车热管理方案 为您的汽车研发保驾护航
  • 原文地址:https://blog.csdn.net/m0_66363962/article/details/126273569