算法题学习---二维数组中的查找

93 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情

题目

描述

在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

[

[1,2,8,9], [2,4,9,12], [4,7,10,13], [6,8,11,15]

]

给定 target = 7,返回 true。

给定 target = 3,返回 false。

数据范围:矩阵的长宽满足 0≤n,m≤500 , 矩阵中的值满足 0≤val≤10^9 进阶:空间复杂度O(1) ,时间复杂度 O(n+m)

示例1

输入:
7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:
true
说明:
存在7,返回true   

示例2

输入:
1,[[2]]
返回值:
false

示例3

输入:
3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:
false
说明:
不存在3,返回false

分析

分析特殊情况

简单分析可知,当二维数组为空时,不管查找什么target,都只需要返回空。

分析一般情况

顺序遍历方法

最容易想到的便是两层遍历,对每一行中的每一个元素进行遍历,与target进行对比,如果相等则返回true,否则最后返回false,如下:

for(auto line : array)
{
    for(auto element : line)
    {
        if(element == target)
        {
            return true;
        }
    }
}
return false;

但是这个方法很明显没有使用二维数组已经排序的信息,所以进行了全局遍历,时间复杂度为O(mn),不符合题意。

路径遍历方法

首先我们观察一下数组中的元素,按行从左到右增大,按列从上到下增大,那么左上角的是最小的元素,右下角的是最大的元素;对于左下角的元素,它总是比它上面的元素大,比它右边的元素小,右上角的元素总是比它下面的元素小,比它左边的元素大。

这样一看,左下角和右下角的元素就有一点像二分查找里面的中点元素了,这里我们考察左下角元素。

  • 首先与target进行比较,如果相等,那就返回true;
  • 如果比target小,说明下一步我们应该找一个比它大的比较,所以应该查看右边的元素;
  • 如果比target大,说明下一步我们应该找一个比它小的比较,所以应该查看上边的元素。

那么直到什么时候我们可以停止查找呢?

  • 首先是我们查找的范围不能跳出二维数组的范围,即如果用x,y表示行号和列号,二维数组有m行,n列,那么我们从(m-1,0)出发,最终我们的x小于0停止,y大于n-1也要停止;
  • 其次是我们考虑最坏的情况,即,我们要寻找的元素在右上角,那么我们最多要走m+n-2步,不会有更多的步数了。

代码示例

逻辑如上面分析所说

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        size_t line = array.size();
        if(line == 0)
        {
            return false;
        }
        size_t column = array[0].size();
        int x = line -1;
        int y = 0;
        int n = line + column - 2;
        while(y < column && x >= 0 && n >= 0)
        {
            if(array[x][y] == target)
            {
                return true;
            }
            else if(array[x][y] < target)
            {
                y++;
            }
            else if(array[x][y] > target)
            {
                x--;
            }
            n--;
        }
        return false;
    }
};