跟learnjiawa一起每天一道算法编程题,既可以增强对常用API的熟悉能力,也能增强自己的编程能力和解决问题的能力,算法和数据结构,是基础中的基础,更是笔试的重中之重。
- 不积硅步,无以至千里;
- 不积小流,无以成江海。
题目描述
牛客网剑指offer编程题第1题–二维数组中的查找,在一个二位数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解题方法1
/**
* 思路就是折半查找,因为数组是有序的,所以可以减少查找次数,
* 不用一个个暴力地取去比较
* */
public static boolean find(int target, int [][] array) {
int length = array[0].length - 1;
for(int i=0; i < array.length; i++){
//将二维数组分解成数个一维数组,逐个查找
int leftindex = 0;
int rightindex = length;
while(leftindex < rightindex -1){
//如果和两个边界值相等,就直接返回true
if(array[i][leftindex] == target || array[i][rightindex] == target){
return true;
}
int rowmid = array[i][(leftindex+rightindex)/2];
if(target == rowmid){
return true;
}else if(target > rowmid){
leftindex = (leftindex+rightindex)/2;
}else if(target < rowmid){
rightindex = (leftindex+rightindex)/2;
}
}
}
return false;
}
解题方法2
/* 思路
* 矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
* 因此从左下角开始查找,当要查找数字比左下角数字大时。右移
* 要查找数字比左下角数字小时,上移,例如
{1,2,8,9},
{2,4,9,12},
{4,7,10,13},
{6,8,11,15}
*/
public static boolean find2(int target, int [][] array) {
int rowCount = array.length;
int colCount = array[0].length;
int i,j;
for(i=rowCount-1,j=0; i>=0 && j<colCount;)
{
if(target == array[i][j])
return true;
if(target < array[i][j])
{
i--;
continue;
}
if(target > array[i][j])
{
j++;
}
}
return false;
}
代码测试
package com.learnjiawa.jzoffer;
/**
* @author zouhuayu
* 2019-11-30-11:21
*/
public class Solution1 {
/**
* 思路就是折半查找,因为数组是有序的,所以可以减少查找次数,不用一个个暴力地取去比较
* */
public static boolean find(int target, int [][] array) {
int length = array[0].length - 1;
for(int i=0; i < array.length; i++){
//将二维数组分解成数个一维数组,逐个查找
int leftindex = 0;
int rightindex = length;
while(leftindex < rightindex -1){
//如果和两个边界值相等,就直接返回true
if(array[i][leftindex] == target || array[i][rightindex] == target){
return true;
}
int rowmid = array[i][(leftindex+rightindex)/2];
if(target == rowmid){
return true;
}else if(target > rowmid){
leftindex = (leftindex+rightindex)/2;
}else if(target < rowmid){
rightindex = (leftindex+rightindex)/2;
}
}
}
return false;
}
/* 思路
* 矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
* 因此从左下角开始查找,当要查找数字比左下角数字大时。右移
* 要查找数字比左下角数字小时,上移
*/
public static boolean find2(int target, int [][] array) {
int rowCount = array.length;
int colCount = array[0].length;
int i,j;
for(i=rowCount-1,j=0; i>=0 && j<colCount;)
{
if(target == array[i][j])
return true;
if(target < array[i][j])
{
i--;
continue;
}
if(target > array[i][j])
{
j++;
}
}
return false;
}
public static void main(String[] args) {
int target = 1;
int[][] array = {{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};
System.out.println(find2(target, array));
}
}
总结
从巧妙地角度来说,第二种方法显然是更胜一筹的,它充分利用了提给条件中地二维素组每一列每一行都是有序地这个条件。不过第一种解题思路显然是更加容易想到的,存在的一个小问题是,它只利用了每一个一维数组,也就是每一行的元素是有序的这一个条件,而没有利用每个一维数组的首位元素也是有序的这个条件,所以还是存在着一定的优化空间,不过这两种解题思路都是满足解题限制的,比暴力解法好了很多。
参考文献
[1]程杰. 大话数据结构. 北京:清华大学出版社, 2011.
更多
对我的文章感兴趣,持续更新中…
关注我,看其他系列博客,《跟凑弟弟一起修炼集合框架》、《Java多线程大闯关》、《Java IO流大闯关》。