【LeetCode】240.搜索二维矩阵II

问题描述

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

示例 1:
在这里插入图片描述

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

在这里插入图片描述

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -109 <= matrix[i][j] <= 109
  • 每行的所有元素从左到右升序排列
  • 每列的所有元素从上到下升序排列
  • -109 <= target <= 109

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

法I:不断缩小矩阵——超时

//搜索二维矩阵
//矩阵的不断缩小,确定i,j,k
class Solution {
public:
	bool searchMatrix(vector<vector<int>>& matrix, int target) {
		int i = 0;
		int j = 0;
		int k = 0;
		while (i <= j && i <= k) {
			k = i;
			j = i;
			//确定j
			while (j < matrix[0].size() && matrix[i][j] < target) {
				j++;
			}
			if (j == matrix[0].size()) {
				j = matrix[0].size() - 1;
			}
			else if (matrix[i][j] == target) {
				return true;
			}
			else {//matrix[i][j] > target
				j--;
			}
			//确定k
			while (k < matrix.size() && matrix[k][i] < target) {
				k++;
			}
			if (k == matrix.size()) {
				k = matrix.size() - 1;
			}
			else if (matrix[k][i] == target) {
				return true;
			}
			else {//matrix[k][i] > target
				k--;
			}
			i++;
		}
		return false;
	}
};

在这里插入图片描述

法II:不断缩小矩阵——通过二分法确定j和k

//j和k的确定都通过二分法来完成
class Solution {
public:
	bool searchMatrix(vector<vector<int>>& matrix, int target) {
		int i = 0;
		int j = matrix[0].size() - 1;
		int k = matrix.size() - 1;
		while (i <= j && i <= k) {
			//确定j
			j = findTargetLess(i, j, target, matrix, 0);
			if (j < i) {
				return false;
			}
			if (matrix[i][j] == target) {
				return true;
			}
			//确定k
			k = findTargetLess(i, k, target, matrix, 1);
			if (k < i) {
				return false;
			}
			if (matrix[k][i] == target) {
				return true;
			}
			i++;
		}
		return false;
	}

	//通过二分法确定j和k的值
	//flag为0代表横数组,为1代表纵数组
	int findTargetLess(int i, int j, int target, vector<vector<int>>& matrix, int flag) {
		int left = i;
		int right = j;
		int mid;
		while (left <= right) {
			mid = (left + right) / 2;
			if (flag == 0) {//横数组
				if (matrix[i][mid] == target) {
					return mid;
				}
				if (matrix[i][mid] < target) {
					left = mid + 1;
				}
				else if (matrix[i][mid] > target) {
					right = mid - 1;
				}
			}
			else {//纵数组
				if (matrix[mid][i] == target) {
					return mid;
				}
				if (matrix[mid][i] < target) {
					left = mid + 1;
				}
				else if (matrix[mid][i] > target) {
					right = mid - 1;
				}
			}
		}
		return right;//right一定在left的左边,right对应的值更小
	}
};

在这里插入图片描述
算法的思路和法I是一致的,不同点在于确定jk此次我采用了二分法,可以降低时间复杂度。还是需要注意一些临界条件。

法III:对每一行进行二分查找

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        for (const auto& row: matrix) {
            auto it = lower_bound(row.begin(), row.end(), target);
            if (it != row.end() && *it == target) {
                return true;
            }
        }
        return false;
    }
};

在这里插入图片描述
在这里插入图片描述

法IV:Z字形查找

在这里插入图片描述

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        int x = 0, y = n - 1;
        while (x < m && y >= 0) {
            if (matrix[x][y] == target) {
                return true;
            }
            if (matrix[x][y] > target) {
                --y;
            }
            else {
                ++x;
            }
        }
        return false;
    }
};

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值