第三十五天
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))
的算法
方法
依据数组中元素的特点,因为数组中每一个数都不相同,那么必然存在这个这么一个顶峰元素,而查找顶峰元素,我们可以使用列或行的最大值来处理(相当于我们给元素组进行一个降维操作,我们有每一行或者每一列的最大值来代表该行或该列)。这样问题就转化成为了一个一维数组中,我们去寻找一个峰值。
对于在一维数组中,寻找峰值的算法,我们可以使用类二分的思想来进行。具体的算法如下:
定义l
和r
,令mid=(l+r)/2
,我们去比较一下mid
和mid-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>();
}
}