牛客网剑指offer-在二维数组中的查找

来源:互联网 发布:mac os官方下载 编辑:程序博客网 时间:2024/06/05 16:05

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


题目解答分析

失败解答1:用二维遍历

  这个题要是按普通的二维遍历来查找的话,也能完成功能,但是就体现不出二维数组原先有序的优势了。

  如果数组非常大的话,会特别浪费时间。

  但是我做的时候还是首先采取了这个二维遍历的方法,因为我开始想的是,我需要读入所有的数据,也只能一个一个读,这已经是一个二维遍历,那就只好在读的时候顺便进行查找了。

  程序如下:


程序尝试1:双层循环#include <iostream>using namespace std;int main(int argc, char* argv[]){    int row = 0, col = 0, t = 0;    int testNum[100][100];    bool isFound = false;    while(cin >> row >> col >> t)    {        isFound = false;        for(int i = 0; i < row ; ++i)        {            for(int j = 0; j < col; ++j)            {                //输入每个数                cin>>testNum[i][j];                //边输入边验证                if(false == isFound && t == testNum[i][j])                {                        //已经找到后就没必要再找了                    isFound = true;                }            }        }        if(true == isFound)        {            cout << "Yes" << endl;        }        else        {            cout << "No" << endl;        }    }    return 0;}

 果然提交以后就显示Time Limit Exceed了。

  想必,未显示的测试用例中必然有很大的二维数组。

 

进一步思考:利用数组有序特点

  所以题目给的有序的条件是必须要用的,但是注意到这个有序也不是单纯的有序,行与行之间也只是上面的元素比下面的元素小的关系,并不代表第二行的数一定大于第一行,比如第一行可以是1,2,3,4,而第二行可以是2,3,4,5。

  先定位行再定位列的想法也不行,因为不论是第一列还是最后一列,都不足以作为本行的键值,因为各行之间的元素还是可能重叠的。而且,比如,目标值t有可能比第一列的所有元素都大,所以想根据第一个元素来查找是不行的。

 

书中的思路:

  从数组中选取数字,和目标数字的关系有三种情况:=,<或>。

  如果是等于则查找成功;

  如果是数组中元素小于要查找的数字,说明要查找的数字应该在当前位置的右边下边。

  如果是数组中元素大于要查找的数字,说明要查找的数字应该在当前位置的左边上边。

  但是这两个区域还有可能有重叠,比如右边或下边会在右下角有重叠。

  解决方法:

  如果查找从右上角开始,如果要查找的数字不在右上角,则每次可以剔除一列或一行。

  也可以从左下角开始,但是不能从左上角或者右下角开始。 

 

别人的解答

  http://www.cnblogs.com/remlostime/archive/2012/11/21/2780352.html

  于是搜到了如上的解答。

  可见这个查找是从矩阵的右上角开始进行的(本行最大,本列最小);

  如果查找成功,则返回;

  如果查找失败,矩阵元素值比t小则下移一行,矩阵元素值比t大则左移一列。

  这样把大小关系和调整的两个方向就分开了,经过一些移动,如果查找成功则返回Yes,如果矩阵走完,则表明没有找到。

  这样是可以实现(实现代码附在后面),可以通过本文所列的测试用例,但是提交到九度上,还是超时了。

  暂时没有解决办法,先休息吧,很晚了。。


解答方法2#include <iostream>using namespace std;int main(int argc, char* argv[]){    int row = 0, col = 0, t = 0;    int testNum[1000][1000];    bool isFound = false;    while(cin >> row >> col >> t)    {                //先将数组全部读入        for(int i = 0; i < row ; ++i)        {            for(int j = 0; j < col; ++j)            {                //输入每个数                cin>>testNum[i][j];            }        }        //标志变量,记录查找是否成功        isFound = false;        //然后进行查找        for(int i = 0, j = col -1; false == isFound && i < row && j >= 0;)        {            //找到之后循环就不必再进行            if(testNum[i][j] == t)            {                isFound = true;            }            else if(testNum[i][j] < t)            {                ++i;                //换到下一行            }            else            {                --j;                //换到前一列            }        }        //最后输出结果        if(true == isFound)        {            cout << "Yes" << endl;        }        else        {            cout << "No" << endl;        }    }    return 0;}


参考九度的博客

#include <iostream>#include <cstdio>using namespace std;string search(int a[][1000], int m, int n, int key){    int i = 0;    int j = n - 1;    while(i < m && j >= 0)    {        if (a[i][j] == key)            return "Yes";        else if (a[i][j] < key)            i++;        else            j--;    }    return "No";}int main(){    int n, m;    int a[1000][1000];    while(scanf("%d%d", &m, &n) != EOF)    {        int key;        scanf("%d", &key);        for(int i = 0; i < m; i++)            for(int j = 0; j < n; j++)                scanf("%d", &a[i][j]);        cout << search(a, m, n, key) << endl;    }}




原创粉丝点击