LeetCode 刷题日志(12, 19)

题目 1901. 寻找峰值 II

难度 : 中等

题目大意:

一个 2D 网格中的 峰值 是指那些 严格大于 其相邻格子(上、下、左、右)的元素。
给你一个 从0 开始编号 的 m x n 矩阵 mat ,其中任意两个相邻格子的值都不相同 。找出 任意一个 峰值 mat[i][j] 并 返回其位置 [i,j]
你可以假设整个矩阵周边环绕着一圈值为 -1 的格子。
要求写出 O ( n l o g m ) O(nlogm) O(nlogm) 或者 O ( m l o g n ) O(mlogn) O(mlogn)的算法
提示:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 500
  • 1 <= mat[i][j] <= 105
  • 任意两个相邻元素均不相等.

思路1:暴力做法

  • 我们可以仿照这题 162. 寻找峰值 题解 ,我们只要从一个点出发,然后 ⌈ \lceil 依据人往高处走 ⌉ \rceil 的想法只需要判断四个方向,然后哪里高就往哪里走,最后走不了的时候就直接返回结果

代码实现:

class Solution {
public:
    vector<int> findPeakGrid(vector<vector<int>>& mat) {
        int n = mat.size(), m = mat[0].size();
        int x = 0, y = 0;
        while (true) {
            if (x + 1 < n && mat[x + 1][y] > mat[x][y]) {
                x += 1;
                continue;
            }
            if (x - 1 >= 0 && mat[x - 1][y] > mat[x][y]) {
                x -= 1;
                continue;
            }
            if (y + 1 < m && mat[x][y + 1] > mat[x][y]) {
                y += 1;
                continue;
            }
            if (y - 1 >= 0 && mat[x][y - 1] > mat[x][y]) {
                y -= 1;
                continue;
            }
            return {x, y};
        }
        return {};
    }
};

时间复杂度 O ( n m ) O(nm) O(nm)

思考怎么优化呢?依据题目给的时间复杂度,要把一个维度优化为 O ( l o g n ) O(logn) O(logn)级别,那么是不是可以考虑和 162. 寻找峰值 题解 的优化思路一样考虑二分呢?

思路二 :二分法

  • 这个我们根据什么来判断二分的区间呢?类比 162. 寻找峰值 题解 的思考方法,以每一行(列)的最大值来判断二分的区间,假设下标为(i, j),根据暴力的思路,我们判断这个点上下的值,即grid[i - 1][j] 和 grid[i][j] 和 grid[i + 1][j]但是要判断一下边界,我们往高处走,这一行的最大值是(i, j)那么说明之后的二分的过程中,只能在i的一侧, 不可能从一侧跨到另外一测
  • 但是为什么这个是正确的呢?

贴一个LeetCode官方题解的证明:官方题解证明

LeetCode 刷题日志(12, 19)_第1张图片

代码实现:

class Solution {
public:
    vector<int> findPeakGrid(vector<vector<int>>& mat) {
        int n = mat.size(), m = mat[0].size();
        auto check = [&](int mid) -> bool {
            int j = max_element(mat[mid].begin(), mat[mid].end()) - mat[mid].begin();
            return !mid || mat[mid - 1][j] < mat[mid][j];
        };
        int l = 0, r = n - 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (check(mid)) l = mid;
            else r = mid - 1;
        }
        int idx = max_element(mat[l].begin(), mat[l].end()) - mat[l].begin();
        return {l, idx};
    }
};

时间复杂度 O ( m l o g n ) O(mlogn) O(mlogn)

  • 库函数max_element(first, second)简介
    定义在range头文件里面,第一个参数是起始位置, 第二个参数是结束位置,返回值是这一段区间内的最大值的位置(迭代器)

【微语】哪怕是一点点进步,也比停滞不前要好。

结束了

你可能感兴趣的:(leetcode,算法,职场和发展)