题目

image.png


个人解答:

题目中明确提出高效,此外数组是升序排列的,因此应该考虑二分查找。

  1. class Solution {
  2. public:
  3. bool searchMatrix(vector<vector<int>>& matrix, int target) {
  4. int m = matrix.size()-1;
  5. int i = 0,n =matrix[0].size()-1;
  6. if(target<matrix[0][0]||target>matrix[m][n])
  7. return false;
  8. if(m==0)
  9. {
  10. for(int j=0;j<=n;j++)
  11. {
  12. if (target==matrix[i][j])
  13. return true;
  14. else if (target<matrix[i][j])
  15. return false;
  16. }
  17. }
  18. while(i<=m)
  19. {
  20. if(target>matrix[i][n])
  21. i++;
  22. else if(target<matrix[i][0])
  23. return false;
  24. else
  25. {
  26. for(int j=0;j<=n;j++)
  27. {
  28. if (target==matrix[i][j])
  29. return true;
  30. else if (target<matrix[i][j])
  31. return false;
  32. }
  33. }
  34. }
  35. return true;
  36. }
  37. };

官方解答:

方法一:两次二分查找

思路:

由于每行的第一个元素大于前一行的最后一个元素,且每行元素是升序的,所以每行的第一个元素大于前一行的第一个元素,因此矩阵第一列的元素是升序的。

我们可以对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素,然后在该元素所在行中二分查找目标值是否存在。

代码:

  1. class Solution {
  2. public:
  3. bool searchMatrix(vector<vector<int>> matrix, int target) {
  4. auto row = upper_bound(matrix.begin(), matrix.end(), target, [](const int b, const vector<int> &a) {
  5. return b < a[0];
  6. });
  7. if (row == matrix.begin()) {
  8. return false;
  9. }
  10. --row;
  11. return binary_search(row->begin(), row->end(), target);
  12. }
  13. };

upper_bound(STL容器函数)
image.png


方法二:一次二分查找

思路:

若将矩阵每一行拼接在上一行的末尾,则会得到一个升序数组,我们可以在该数组上二分找到目标元素。

代码实现时,可以二分升序数组的下标,将其映射到原矩阵的行和列上。

代码:

  1. class Solution {
  2. public:
  3. bool searchMatrix(vector<vector<int>>& matrix, int target) {
  4. int m = matrix.size(), n = matrix[0].size();
  5. int low = 0, high = m * n - 1;
  6. while (low <= high) {
  7. int mid = (high - low) / 2 + low;
  8. int x = matrix[mid / n][mid % n];
  9. if (x < target) {
  10. low = mid + 1;
  11. } else if (x > target) {
  12. high = mid - 1;
  13. } else {
  14. return true;
  15. }
  16. }
  17. return false;
  18. }
  19. };

image.png