二维数组查找

1:题目描述

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

 

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

给定 target = 5,返回 true

给定 target = 20,返回 false

 

限制:

0 <= n <= 1000

0 <= m <= 1000

2:题目分析

  •   由于题目中是二维数组查找某一个数,很显然可以直接通过遍历二维数组来找到目标数,所以第一种方法通过对每一行的数据进行二分法的查找数据来解决问题。当然该方法的时间复杂度为每一行为O(logn),共有m列,所以时间复杂度为O(mlogn),如果每一行不通过二分法,则时间复杂度为O(n*m)。
  • 第二种方法,由于二维数组的每一行从左到右为从小到大,每一列从上到下为从小到大。所以可以利用这个特性来遍历数据。假设当前位置数据为temp,则target的大小关系和位置关系有以下情况;
    • target > temp,则target的位置只可能在temp有右侧和下侧。
    • target < temp,只可能在temp的左侧或者上侧。

  分析上面第二种方法,这个可以作为一个解题思路来做,但是起始位置的不同会对程序造成不同的影响,如果我们选择左下角作为起始位置,则情况会简单多,因为这种情况下,target若大于temp,则target所在位置的列的所有数据都比temp小,所在可以清除该列,同理若target小于temp,则temp所在行的所有数据都比target大!可以不断缩减范围数组的大小,直到找到target或者越界。

3:代码实现

public boolean findNumberIn2DArray(int[][] matrix, int target) {
        for(int[] array:matrix){
            if(binarySearch(array,target) == true){
                return true;
            }
        }
        return false;
    }

    public boolean binarySearch(int[] array,int target){
        if(array == null){
            return false;
        }
        int rightLimitaion = array.length-1;
        int leftLimitaion = 0;
        int middleIndex = 0;
        while(true){
            middleIndex = (leftLimitaion + rightLimitaion)/2;
            if(array[middleIndex]==target) {
                return true;
            }
            else{
                //二分查找的false标志位:左限大于右限时。return false
                if(leftLimitaion > rightLimitaion){
                    return false;
                }
                else{
                    if(array[middleIndex]>target){
                        //如果,当前中点值大target,则把右侧位置改为middleIndex-1
                        //因为前面已经判断了array[middleIndex]是不是等于target,
                        //所以这里可以直接-1;
                        rightLimitaion = middleIndex-1;
                    }
                    else
                    if(array[middleIndex]<target) {
                        //与上面判断类似
                        leftLimitaion = middleIndex+1;
                    }
                }
            }
        }

上面方法是暴力法(二分)。

下面就是前面说的第二种方法。

    public boolean s1(int[][] matrix, int target) {
        int rows = matrix.length;
        if (rows == 0) {
            return false;
        }

        int cols = matrix[0].length;
        if (cols == 0) {
            return false;
        }

        int number = 0;
        int x = rows-1;
        int y = 0;
        //从左上到右下的遍历,找到目标数
        while(true){
            //如果当前位置小于target,则当前行可以被清除
            if(matrix[x][y]<target){
                y++;
            }
            else{
                //如果当前位置大于target,则当前列可以被清除
                if(matrix[x][y]>target){
                    x--;
                }
                else{
                    //如果当前位置等于target,则return true
                    return true;
                }
            }
            //如果越界了,还没有返回true,则意味着没有找到taget,返回false
            if(x<0||y>=cols){
                return false;
            }

        }
    }

 

 

posted @ 2020-03-04 10:49  大朱123  阅读(190)  评论(0编辑  收藏  举报