1.引例(简单形式)
在一个二维数组中,每一行按从左到右递增的顺序排列,下一行的第一个元素大于上一行最后一个元素,找出目标数是否在此二维数组中。
1.1分析
此题输入为二维数组,其实质是一维有序数组的问题,将二维数组的元素索引对应一维数组,进而采用二分搜索方法求解。
1 public static boolean isArrayItem(int[][] array, int target) { 2 if (array.length == 0) {return false;} 3 int len = array.length * array[0].length; 4 int col = array[0].length; 5 int lo = 0; 6 int hi = len - 1; 7 while (lo <= hi) { 8 int mid = (lo + hi) / 2; 9 if (array[mid / col][mid % col] == target) { 10 return true; 11 } else if (array[mid / col][mid % col] > target) { 12 hi = mid - 1; 13 } else { 14 lo = mid + 1; 15 } 16 } 17 return false; 18 }
复杂度分析:时间复杂度O(logn),空间复杂度O(1)。
2.题目描述
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
3.分析边界条件及测试用例
1.输入数组为空,测试用例为{};
2.输入的目标值超出数组的范围之内,测试用例为{{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}} ,target = 16;
3.正常的测试案例,输入数组为{{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}} ,target = 5和target = 7。
4.问题求解
求解思路,对于目标值来说,分析输入数组的规律,可以知道每行的最后一个元素比这一行所有元素都大,比其所在列的所有元素都小,通过比较该元素于目标元素,每比较一次就能排除一行或一列元素,减小了运算代价。
1 public static boolean isSpecificArrayItem(int[][] array, int target) { 2 if (array.length == 0) {return false;} 3 int row = array.length; 4 int col = array[0].length; 5 if (target < array[0][0] || target > array[row - 1][col - 1]) { 6 return false; 7 } 8 int rIndex = 0; 9 int cIndex = col - 1; 10 while(rIndex < row && cIndex >= 0) { 11 if (array[rIndex][cIndex] == target) { 12 return true; 13 } else if (array[rIndex][cIndex] > target) { 14 cIndex--; 15 } else { 16 rIndex++; 17 } 18 } 19 return false; 20 }
复杂度分析:时间复杂度O(m+n)(m,n为二维数组两个维度),空间复杂度O(1)。