390. 找峰值 II

描述

一个整数矩阵有如下一些特性:
相邻的整数都是不同的
矩阵有 n 行 m 列。
对于所有的 i < m, 都有 A[0][i] < A[1][i] && A[n - 2][i] > A[n - 1][i].
对于所有的 j < n, 都有 A[j][0] < A[j][1] && A[j][m - 2] > A[j][m - 1].
我们定义一个位置 P 是一个峰,如果有 A[j][i] > A[j+1][i] && A[j][i] > A[j-1][i] && A[j][i] > A[j][i+1] && A[j][i] > A[j][i-1]。
找出该矩阵的一个峰值元素,返回它的坐标。

注意事项

可能会存在多个峰值,返回任意一个即可。

思路

从中间行的最大值往上或下寻找比该元素更大的值攀爬,从而使矩阵在 O(n) 的时间操作下规模减小了一半,然后在刚刚元素所在列寻找最大值,对当前规模为原来一半的矩阵进行重复的寻找操作

代码

// O(m + n) 算法
// 利用 flag 来对行列进行交替二分,flag = true 时二分行,flag = false 时二分列
// 每一次递归调用 x1, x2, y1, y2 都会更新
class Solution {
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    public List find(int x1, int x2, int y1, int y2,
                              int[][] A, boolean flag) {
        
        if (flag) {
            int mid = x1 + (x2 - x1) / 2;
            int index = y1;
            for (int i = y1; i <= y2; ++i) {
                if (A[mid][i] > A[mid][index]) {
                    index = i;
                }
            }
                    
            if (A[mid - 1][index] > A[mid][index]) {
                return find(x1, mid - 1, y1, y2, A, !flag);
            }
            else if (A[mid + 1][index] > A[mid][index]) {
                return find(mid + 1, x2, y1, y2, A, !flag);
            }
            else {
                return new ArrayList(Arrays.asList(mid, index));
            }
        } else {
            int mid = y1 + (y2 - y1) / 2;
            int index = x1;
            for (int i = x1; i <= x2; ++i) {
                if (A[i][mid] > A[index][mid]) {
                    index = i;
                }
            }
                    
            if (A[index][mid - 1] > A[index][mid]) {
                return find(x1, x2, y1, mid - 1, A, !flag); 
            }
            else if (A[index][mid + 1] > A[index][mid]) {
                return find(x1, x2, mid + 1, y2, A, !flag);
            }
            else {
                return new ArrayList(Arrays.asList(index, mid));
            }
        }
    }
    
    public List findPeakII(int[][] A) {
        int n = A.length;
        int m = A[0].length;
        return find(1, n - 2, 1, m - 2, A, true);
    }
}

你可能感兴趣的:(390. 找峰值 II)