【leetcode刷题第35天】1060.有序数组中缺失的元素、1901.找出顶峰元素、1380.矩阵中的幸运数

第三十五天

1060 有序数组中的缺失元素

现有一个按 升序 排列的整数数组 nums ,其中每个数字都 互不相同

给你一个整数 k ,请你找出并返回从数组最左边开始的第 k 个缺失数字。

方法

由于数组是升序排列的,因此我们可以考虑使用二分来解决这个问题,容易知道,对于下标为i的元素,它和首元素之间空出来的元素的个数是nums[i]-nums[0]-i,而我们要找的是第k个缺失的元素,因此,我们只需要找出和首元素之间间隔不超过k的最大下标,然后再加上和k的差值,就是我们想要找到的那个第k个缺失的元素。

class Solution {
    public int missingElement(int[] nums, int k) {
        int l = 0, r = nums.length - 1;
        //二分查找最大的下标 
        while (l <= r){
            int mid = (l + r) >> 1;
            if (nums[mid] - nums[0] - mid >= k){
                r = mid - 1;
            }
            else{
                l = mid + 1;
            }
        }
        return nums[r] + k - (nums[r] - nums[0] - r);
    }
}

1901 找出顶峰元素Ⅱ

一个 2D 网格中的 顶峰元素 是指那些 严格大于 其相邻格子(上、下、左、右)的元素。

给你一个 从 0 开始编号m x n 矩阵 mat ,其中任意两个相邻格子的值都 不相同 。找出 任意一个 顶峰元素 mat[i][j]返回其位置 [i,j]

你可以假设整个矩阵周边环绕着一圈值为 -1 的格子。

要求必须写出时间复杂度为 O(m log(n))O(n log(m)) 的算法

方法

依据数组中元素的特点,因为数组中每一个数都不相同,那么必然存在这个这么一个顶峰元素,而查找顶峰元素,我们可以使用列或行的最大值来处理(相当于我们给元素组进行一个降维操作,我们有每一行或者每一列的最大值来代表该行或该列)。这样问题就转化成为了一个一维数组中,我们去寻找一个峰值。

对于在一维数组中,寻找峰值的算法,我们可以使用类二分的思想来进行。具体的算法如下:

定义lr,令mid=(l+r)/2,我们去比较一下midmid-1,也就是去考察一下这个小区间上的增减性,如果我们发现,在这个小区间上,它是递增的,那么在mid的右边一定存在一个峰值元素,否则mid左边一定存在一个峰值元素。通过不断缩小寻找范围,最终找到这个峰值元素。

返回答案时,我们只需要在答案所在的列,寻找该列中的最大元素的位置即可。

class Solution {
    public static int[] dx = {0, 0, 1, -1};
    public static int[] dy = {1, -1, 0, 0};
    public static int xLength;
    public static int yLength;
    
    public int[] findPeakGrid(int[][] mat) {
        xLength = mat.length;
        yLength = mat[0].length;
        int l = 0, r = yLength - 1;
        while (l <= r){
            int mid = (l + r) >> 1;
            int curMax = -1;
            int preMax = -1;
            for (int i = 0; i < xLength; ++i){
                curMax = Math.max(curMax, mat[i][mid]);
                if (mid - 1 >= 0) preMax = Math.max(preMax, mat[i][mid - 1]);
            }
            if (mid - 1 < 0 || preMax < curMax) l = mid + 1;
            else r = mid - 1;
        }
        int Max = -1, index = -1;
        for (int i = 0; i < xLength; ++i){
            if (mat[i][r] > Max) {
                Max = mat[i][r];
                index = i;
            }
        }
        return new int[]{index ,r};
    }
}

1380 矩阵中的幸运数

给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

幸运数是指矩阵中满足同时下列两个条件的元素:

  • 在同一行的所有元素中最小

  • 在同一列的所有元素中最大

方法

由于矩阵中各个元素皆不相同,因此,在一个矩阵中至多存在一个幸运数,证明略。

因此我们只需要把这个唯一的幸运数找出来即可。

我们维护每一行的最小值和每一列的最大值,然后遍历整个数组,如果发现某个位置所在行的最小值和所在列的最大值相同,那么这个位置上的数就是答案。

class Solution {
    public List<Integer> luckyNumbers (int[][] matrix) {
        int[] lMax = new int[matrix.length];
        int[] cMax = new int[matrix[0].length];
        for (int i = 0; i < matrix.length; ++i){
            lMax[i] = matrix[i][0];
            for (int j = 0; j < matrix[0].length; ++j){
                lMax[i] = Math.min(lMax[i], matrix[i][j]);
            }
        }

        for (int j = 0; j < matrix[0].length; ++j){
            for (int i = 0; i < matrix.length; ++i){
                cMax[j] = Math.max(cMax[j], matrix[i][j]);
            }
        }

        for (int i = 0; i < matrix.length; ++i){
            for (int j = 0; j < matrix[0].length; ++j){
                if (lMax[i] == cMax[j]) {
                    ArrayList<Integer> res = new ArrayList<>();
                    res.add(matrix[i][j]);
                    return res;
                }
            }
        }
        return new ArrayList<Integer>();
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值