题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。输入一个整数key,判断二维数组中是否含有该整数。
分析:
例如有如下二维数组,习惯上,可能我们会从二维数组第1个元素下手,判断其是否等于key,若第1个元素小于key,则再判断下面红色整数部分(加粗部分判断重叠部分):
1 2 3 5
4 5 8 12
8 12 14 21
如果按照上面的方式查找,则每个元素的判断都会有重复判断的区域,问题变得更加复杂。
我们可以观察一下数组的规律:数组从左到右,从上到下都是递增的,左上角(右下角的元素也同理)的整数处于当前行、列的最小值,除非该元素就是key或者大于key(查找失败),否则每次查找都没办法舍弃某行或某列,只能排除一个元素。而如果我们从右上角的元素出发,该元素是行的最大值,列的最小值,我们可以利用这个性质使每次查找都排除一行或一列(该元素大于key排除列,小于key排除行)。
以下是算法实现代码(从右上角元素开始判断):
1 package com.yyl.arithmetic.array; 2 3 public class TwoDimensionSearch { 4 5 public static boolean find(int[][] array, int key){ 6 if(array != null && array.length != 0){ 7 int row = array.length - 1; //行数-1 8 int column = array[0].length - 1; //列数-1 9 print(array, 0, column, row); 10 int i = 0, j = column; 11 while(i <= row && j >= 0){ 12 if(array[i][j] > key){ 13 j--; //j列均大于key 14 }else if(array[i][j] < key){ 15 i++; //i行均小于key 16 }else{ 17 return true; 18 } 19 print(array, i, j, row); 20 } 21 } 22 return false; 23 } 24 25 public static void print(int[][] array, int row, int column, int rowCount){ 26 int i = row, j; 27 for(; i <= rowCount; i++){ 28 for(j = 0; j <= column; j++){ 29 System.out.print(array[i][j] + " "); 30 } 31 System.out.println(); 32 } 33 System.out.println(); 34 } 35 36 public static void main(String[] args) { 37 int[][] array = {{1,2,3,5}, {4,5,8,12}, {8,12,14,21}}; 38 System.out.println(find(array, 8)); 39 } 40 }
输出结果:
1 2 3 5
4 5 8 12
8 12 14 21
4 5 8 12
8 12 14 21
4 5 8
8 12 14
true