横纵有序矩阵之元素查找
问题描述:
给定一矩阵(二维数组存储)和一个目标元素K,其中矩阵的每一行从做到右递增,每一列从上到下递增,用尽量高效的算法判断目标元素K是否在存在矩阵中。
分析:
首先想到的就是暴力方法,依次遍历二维数组汇总每一个元素时左比较判断,但是很可惜效率并不高。
考虑到该二维数组与普通的二维数组不同,利用该二维数组横向和纵向分别有序的特点,应该有其他高效的算法。
不难发现,该二维数组实际上隐含的存在一些已然有序的元素序列:从某一行一直往右,然后再往下走;途径的元素必然是递增有序序列。
如下图所示:
有序的序列在查找目标元素方面有天然的优势,从这些已然有序的序列入手,就可以很方便的逐步缩小查找范围。
从第一行的最右元素开始(也就是右上角的元素),判断其与目标元素K的大小:
如果该元素大于目标元素,由于该元素是该元素所在列的最小值,因此可以确定该列所有元素没有命中的可能性,排除掉该列;
如果该元素小于目标元素,由于该元素是该元素所在行的最大值,因此可以确定该行所有元素没有命中的可能性,排除掉该行;
如果该元素等于目标元素,命中,结束。
每次在排除掉一行或者一列后,都选取剩余二维表的右上角作为新的筛选判断条件,如果未命中,那么总能保障每次都排除掉一行或者一列元素。
其本质的思想就是利用二维数组的有序序列特点再结合减治算法思想,逐步缩小查找访问,比暴力求解算法的效率高。
实现:
package agother; /*本质上就是利用减治的思想*/ public class Ary2D { public static boolean find(int[][] ary,int target){ int i = 0,j = ary[0].length-1;//从第一行的最右端开始 while(i<ary.length && j >=0){ if(ary[i][j] == target){//命中 return true; }else if(ary[i][j] > target){//排除掉第j列 j--; }else {//排除掉第i行 i++; } } return false; } public static void main(String[] args) { // TODO Auto-generated method stub try { int[][] ary = new int[3][6];//测试数组 ary[0] = new int[]{1,2,4,8,10,50}; ary[1] = new int[]{5,8,10,11,15,60}; ary[2] = new int[]{9,12,15,20,30,70}; System.out.println(find(ary, 15)); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }