01 在递增[下面的<上面的, 左边的<右边的]二维数组中查找给定的值
2015-12-28 21:50
423 查看
前言
本博文部分图片, 思路来自于剑指offer 或者编程珠玑问题描述
满足条件的矩阵
思路
书中给出的思路有两种思路一 : 从第一行开始进行查找, 因为每一行的数据有序, 所以可以使用二分查找, 剪枝条件为给定的数据小于给定行的第一个数字[给定行最小的]
思路二 : 从arr[0][col-1]开始查找, arr[0][col-1]的特征为当前行的其他数据都小于该数据, 当前列的其他数据都大于该数据, 这就为我们构造了两个剪枝迭代的条件
1 如果给定的数字大于arr[0][col-1] 则可以剪去当前行[row ++]
2 如果给定的数字小于arr[0][col-1] 则可以剪去当前列[col –]
arr[0][col-1]
参考代码
/** * file name : Test22FindNumberInTwoDimen.java * created at : 10:48:18 AM Jun 4, 2015 * created by 970655147 */ package com.hx.test04; public class Test22FindNumberInTwoDimen { // 从二维数组[左边的小于右边的, 上面的小于小面的]中找到一个数 from 剑指offer page40 public static void main(String []args) { int[][] arr = { {1, 2, 8, 9 }, {2, 4, 9, 12 }, {4, 7, 10, 13 }, {6, 8, 11, 15 } }; int tar = 11; findNumberInArr01(arr, tar); findNumberInArr02(arr, tar); findNumberInArr03(arr, tar); } // 思路 : 一行一行的找, 剪枝条件 : 第一个元素大于tar public static void findNumberInArr01(int[][] arr, int tar) { for(int row=0; row<arr.length; row++) { if(arr[row][0] > tar) { break ; } else { int col = binarySearch(arr[row], tar); if(col != -1) { Log.log(row, col); } } } } // binarySearch private static int binarySearch(int[] arr, int tar) { int low = 0, high = arr.length - 1, mid; while(low <= high) { mid = (low + high) >> 1; if(arr[mid] > tar) { high = mid - 1; } else if(arr[mid] < tar) { low = mid + 1; } else { return mid; } } return -1; } // 思路 : 初始row为0, col为arr[0].length-1 // 遍历条件 : row小于arr.length 并且col大于等于0 否则视为找不到 // 如果当前元素小于tar 则可以剔除当前行[当前行的元素均小于当前元素] // 如果当前元素大于tar 则可以剔除当前列[当前列的元素均大于当前元素] // 否则 找到目标元素 public static void findNumberInArr02(int[][] arr, int tar) { int row = 0, col = arr[0].length - 1; while(row < arr.length && col >= 0) { if(arr[row][col] > tar) { col --; } else if(arr[row][col] < tar) { row ++; } else { Log.log(row, col); break; } } } // 思路 和前面一种方法差不多, 不过初始位置不一样, 导致了逻辑有一些差别 public static void findNumberInArr03(int[][] arr, int tar) { int row = arr.length - 1, col = 0; while(row < arr.length && col >= 0) { if(arr[row][col] > tar) { row --; } else if(arr[row][col] < tar) { col ++; } else { Log.log(row, col); break; } } } }
效果截图
总结
对于思路一 : n * n的矩阵中, 需要计算n次二分查找, 每一次时间复杂度为log(n), 总的时间复杂度为O(nlog(n) ), 假设剪枝减掉一半, 复杂度为O((1 /2) nlog(n) ), 忽略掉常数项, 时间复杂度依然为O(nlog(n) )对于思路二 : n * n的矩阵中, 因为每一次迭代, 都必然剪去一行, 或者一列, 所以最多的尝试次数为n次, 时间复杂度为O(n)
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树