[关闭]
@w1024020103 2017-06-21T20:11:44.000000Z 字数 2083 阅读 648

Search a 2D Matrix

LeetCode LintCode


image_1bj547gp218uo1tct1qnm1gtk13vr9.png-45.9kB

我想出来的方法比较straightforward, 就是先确定行,再确定列。两次使用binary search. 其中实施起来有不少细节容易错,值得细细推敲。值得留意的是,这道题可以看出来LeetCode的通过检测比LintCode要严格,以后都要到LeetCode上测试。

  1. public class Solution {
  2. public boolean searchMatrix(int[][] matrix, int target) {
  3. if ( matrix == null || matrix.length == 0){
  4. return false;
  5. }
  6. if (matrix[0] == null || matrix[0].length == 0) {
  7. return false;
  8. }
  9. int row = matrix.length;
  10. int column = matrix[0].length;
  11. int start = 0;
  12. int end = matrix.length - 1;
  13. while (start + 1 < end){
  14. int mid = start + (end - start) / 2;
  15. if ( target == matrix[mid][0]){
  16. return true;
  17. } else if (target > matrix[mid][0]){
  18. start = mid ;
  19. } else {
  20. end = mid;
  21. }
  22. }
  23. if (target >= matrix[end][0]){
  24. row = end;
  25. } else if (target >= matrix[start][0]) {
  26. row = start;
  27. } else{
  28. return false;
  29. }
  30. start = 0;
  31. end = column - 1;
  32. while (start + 1 < end){
  33. int mid = start + ( end - start ) / 2;
  34. if ( target == matrix[row][mid]){
  35. return true;
  36. } else if (target < matrix[row][mid]) {
  37. end = mid;
  38. } else{
  39. start = mid;
  40. }
  41. }
  42. if (matrix[row][start] == target) {
  43. return true;
  44. }
  45. if (matrix[row][end] == target){
  46. return true;
  47. }
  48. return false;
  49. }
  50. }

这个首先要套用老师讲的二分法的模版:

image_1bj55sua7mh81lr512l11kjgci2m.png-71kB

首先要注意几种特殊情况,这里特别提一下以下情况:

  1. if (matrix[0] == null || matrix[0].length == 0) {
  2. return false;
  3. }

matrix[0] == null

表示的是有一个[ ],但它里面的2D array还没有初始化;而

matrix[0].length == 0

则是代表 [ [ ] ] 这样子的情况。

我们第一步先确定target所在的行,以mid行的第一列为标准作为判断来变化start, end. 退出循环后,只剩下start, endl两行,再检查target与这两行第一列的关系。首先检查第二行第一列跟target的关系,最终确定行数。

第二步,继续二分法确定列数。循环条件按照模版很类似,循环内容也是模版的A[mid] ==, <, > target 这几种情况。循环结束只需要再多检查该行的start, end两列是否为target。

几乎都是按照这个模版:

start + 1 < end
start + (end - start) / 2
A[mid] ==, <, >
A[start] A[end] ? target

第二种方法是用一次二分法。

  1. public class Solution {
  2. public boolean searchMatrix(int[][] matrix, int target) {
  3. if ( matrix == null || matrix.length == 0){
  4. return false;
  5. }
  6. if (matrix[0] == null || matrix[0].length == 0) {
  7. return false;
  8. }
  9. int row = matrix.length;
  10. int column = matrix[0].length;
  11. int start = 0;
  12. int end = row * column - 1;
  13. while (start + 1 < end) {
  14. int mid = start + (end - start) / 2;
  15. if (target == matrix[mid / column][mid % column]){
  16. return true;
  17. } else if (target < matrix[mid / column][mid % column]){
  18. end = mid;
  19. } else {
  20. start = mid;
  21. }
  22. }
  23. if (target == matrix[start / column][start % column]){
  24. return true;
  25. }
  26. if (target == matrix[end / column][end % column]){
  27. return true;
  28. }
  29. return false;
  30. }
  31. }

感觉这个方法胜在抽象思维,将2d array整体抽象成 col * row 个元素。这里的end定义为最后一个元素的index, 所找到的mid是所有元素最中间的那个,而跟行列无关。 循环结束后,我们的start, end直接是相邻的两个元素的index, 所以再检查这两个元素即可。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注