面试题3-二维数组中的查找
基础知识
数组是最简单的一种数据结构,它占据一块连续的内存并按照顺序存储数据。在创建数组的时候,必须首先指定数组的容量大小,然后根据大小来分配内存,一经建立之后数组的大小便不能更改,这就造成了其空间利用的效率不够高。但是数组的内存是连续的,可以根据下标在O(1)的时间内读写任意的元素,因此它的时间效率很高。
在不同的编程语言中,都存在动态数组,如C++中的Vector,Java中的ArrayList。这些动态数组都有初始容量,当数据的数目超过数组的初始容量的时候,重新分配一块更大的空间,把之前的数据复制到新的数组中去,释放之前的内存,这样减少了内存的浪费。但是每一次的扩容都会有大量的额外操作,这会对时间性能造成影响,因此在使用动态数组的时候要尽量减少改变数组容量的次数。
题目
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成提个函数输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解题思路:
- 这道题暴力的解法是两层的循环逐一的查找,显然这种复杂度O(mn)的算法是不可取的。
- 可以在此基础之上进行改进,每一行使用二分查找的方法,减少查找的次数,那么复杂度就能下降到O(mlgn)。
- 首先比较二维数组右上角的数字,若和目标数据相等,查找结束,如果该数字大于要查找的数字,则剔除这个数字所在的列;如果该数字小于要查找的数字,则剔除该数字所在的行。这样一行一列的逐步缩小要查找的范围,最后找到数字或者范围为空。(仔细想想这种解法有点动归的意思)这种思想的算法复杂度最坏情况下为O(m+n)。算法还是很神奇的。
代码
二分:
- public class Solution { 
-     public boolean Find(int target, int [][] array) { 
-         if( array == null) 
-             return false; 
-           
-         int row = array.length; 
-         //System.out.println(row); 
-         int col = array[0].length; 
-          boolean res = false; 
-         if(row > 0 && col >0){ 
-             int min = array[0][0]; 
-             int max = array[row-1][col-1]; 
-             if(target < min || target > max) 
-                 return false; 
-             //System.out.println("test"); 
-             int i = 0; 
-             
-            while( i < col){ 
-                int low = 0,high = row - 1, mid = 0; 
-                while(low <= high){ 
-                    mid = low + (high - low)/2; 
-                    if(target == array[i][mid]){ 
-                        res =  true; 
-                        return res; 
-                    } 
-                    if(target > array[i][mid]){ 
-                        low = mid + 1; 
-                    }else{ 
-                        high = mid - 1; 
-                    } 
-                } 
-               i ++; 
-            } 
-         } 
-         return res; 
-           
-     } 
- } 
从右上删减行列减少范围:
- public class Solution { 
-     public boolean Find(int target, int [][] array) { 
- 		int row = array.length; 
-         if(row == 0) 
-             return false; 
- 		int col = array[0].length; 
-         int i = 0, j = col - 1; 
-         while(i < row && j >=0 ){ 
-             if(target == array[i][j]) 
-                 return true; 
-             if(target > array[i][j]) 
-                 i++; 
-             else 
-                 j--; 
-         } 
-         return false; 
-     } 
- } 
