杨氏矩阵查找算法

简介: 杨氏矩阵是一种特殊矩阵,其每一行和每一列都是递增的。要在一个杨氏矩阵中查找特定数值,可以从右上角或左下角开始,通过比较当前元素与目标值的大小来决定向下或向左移动,直到找到目标值或超出边界。这种方法的时间复杂度为O(N)。文中还提供了一段C语言代码实现此查找算法,并给出了牛客网上的相关练习题链接。

一、杨氏矩阵介绍


杨氏矩阵种,每一行的数都从左到右递增,每一列的数都从上到下递增。如下图是一个简单的杨氏矩阵:



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

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



二、查找算法


1.查找思路


杨氏矩阵是很有特点的,它有规律递增的特点决定了针对表中的任一元素,它的下方和右方的数一定大于我,左方和上方的数一定小于我,所以查找的时候可利用这一特点,从右上角或者左下角来找。


因为这两个位置的大于小于有区分度。例如,若选择从右上角找,那么没有上边和右边,而下边一定比我大,左边一定比我小。那么,如果要查找的数比遍历到的元素大,那我就向下查找;如果比遍历到的元素小,那我就向左查找。


这样查找的次数只有x+y-1次,符合题目中要求的O(n)。


2.步骤






3.代码


int Check(int a[ROW][COL],int row,int col,int k) {
  int x = 0;
  int y = col - 1;
  while(x <= row-1 && y >= 0){
    if (k > a[x][y]) {    //比我大就向下
      x++;
    }
    else if (k < a[x][y]) {    //比我小就向左
      y--;
    }
    else {
      return 1;    //相等:找到了
    }
  }
  return 0;    //没有找到
}
 
int main() {
  int a[ROW][COL] = { {1,2,3,4},{5,6,7,8},{9,10,11,12}};//示例
  int k = 0;    //要查找的数
 
  printf("请输入你要找的数:\n");
  while(~scanf("%d", &k)){
    if (Check(a, ROW, COL, k)) {
      printf("找到了!\n");
    }
    else {
      printf("该数不存在!\n");
    }
  }
 
  return 0;
}



三、杨氏矩阵例题


牛客网习题链接


https://www.nowcoder.com/practice/abc3fe2ce8e146608e868a70efebf62e






代码


该题相当于是前面杨氏矩阵查找的直接运用。注意,当题干中出现 “一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序 这样的描述时,要立马反应过来它是杨氏矩阵。可能不会每道题的矩阵都像{{1,2,3,4},{5,6,7,8},{9,10,11,12}}这样规整,但只要关注并发现它的行按一定顺序(从左到右或从右到左)递增,且列也按一定顺序(从上到下或从下到上)递增,那么就可以运用杨氏矩阵算法。(有时候可能题干数组会是从右向左递增,从下向上递增,刚好和杨氏矩阵反一反,但方法通用。)



bool Find(int target, int** array, int arrayRowLen, int* arrayColLen ) {
  int x = 0;
  int y = *arrayColLen - 1;
  while(x < arrayRowLen && y >= 0){
    if(array[x][y] > target) {
      y--;
    }else if(array[x][y] < target) {
      x++;
    }else{
      return true;
    }
  }
  return false;
}


特别注意


针对这串代码,这里必须附上特别说明。传二维数组入函数,函数头写了形参为int** array,注意这并不是直接传二维数组名时的形参接收方式。

若实参部分直接传二维数组数组名array,则形参应写为:


//列参数不可省略
void fun(int array[][col]);

 


//一维数组指针
void fun(int (*array)[col]);


而用int** array接收,则调用方应该这样写:


#include<stdio.h>
 
bool Find(int target, int** array, int arrayRowLen, int* arrayColLen ) {
  int x = 0;
  int y = *arrayColLen - 1;
  while(x < arrayRowLen && y >= 0){
    if(array[x][y] > target) {
      y--;
    }else if(array[x][y] < target) {
      x++;
    }else{
      return true;
    }
  }
  return false;
}
 
int main(){
  int a1[]={1,2,8,9};
  int a2[]={2,4,9,12};
  int a3[]={4,7,10,13};
  int a4[]={6,8,11,15};
  
  int* p[] = {a1,a2,a3,a4};
  int arrayRowLen = 4;
  int arrayColLen = 4;
    //传入指针数组的数组名,数组p内的元素是指针类型,存放的是另外四个一维数组名
  printf("%d",Find(100, p,arrayRowLen ,&arrayColLen));
  
  return 0;
}


四、总结


概括来说,杨氏矩阵查找的算法是根据杨氏矩阵中数递增规律特点设计的,而这种设计算法的思路可以迁移。若题干变换为其它类型的、其中数具有变化规律的矩阵,要能想起杨氏矩阵的查找算法,并尝试将这种设计的思路迁移到变式中去。

相关文章
|
存储 算法
【查找算法】折半查找法
【查找算法】折半查找法
|
4月前
|
存储 算法 Java
【算法系列篇】二分查找——这还是你所知道的二分查找算法吗?
【算法系列篇】二分查找——这还是你所知道的二分查找算法吗?
|
3月前
|
算法 搜索推荐 Java
二分查找算法详解及实现
二分查找算法详解及实现
52 2
|
4月前
|
算法 索引
算法思想总结:二分查找算法
算法思想总结:二分查找算法
|
4月前
|
算法 测试技术 API
深入理解二分查找算法(一)
深入理解二分查找算法(一)
|
4月前
|
存储 算法 C#
C# | 二分查找算法的实现
二分查找法一种在**有序数组**中查找目标值的算法。划重点——“**有序**”,与需要遍历整个数组的查询算法不同,二分查找法通过将数组分成两部分来快速定位目标值所在的位置。 它的主要好处在于它的效率很高。因为它能够通过每次排除一半的元素来快速缩小搜索范围,因此在大型数据集上使用二分查找法可以显著提高查找速度。
46 0
|
算法 C++
【基础算法】顺序查找 折半查找 & C++实现
顺序查找比较简单,就是顺序遍历我们所要查找的内容,判断并找出相应的目标数。比较简单,在这里不用图形说明程序实现具体情况。当面临大量数据时,顺序查找的效率非常低,时间复杂度大,所以会采用其他方法进行查找。
132 0
【基础算法】顺序查找 折半查找 & C++实现
|
算法
二分查找算法
以整型升序数组arr为例,将数组分为两部分:数组大小为size,设置数组下标left、mid、right,初始时分别为首元素下标0、中间元素下表(right-left)/2和最后元素下标 size-1,左部分为left-mid,右部分为 mid-right 设查找值为x,比较x与mid的大小。
50 0
|
算法
算法篇-杨氏矩阵
算法篇-杨氏矩阵
85 0
|
算法
04查找算法:顺序查找法、二分查找法
04查找算法:顺序查找法、二分查找法
120 0
04查找算法:顺序查找法、二分查找法