您的位置:首页 > Web前端

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, 所以请大家指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  剑指offer 算法 java