博客
两种可行方法:
方法1:y总方法,详细参考视频。
class Solution extends Getvalue {
public int[] getMinimumValue(int n) {
if(n == 1) return new int[]{0, 0};
int l = 0 , r = n - 1;
int mid = - 1, minx = Integer.MAX_VALUE, idx = -1;;
while(l <= r) { //l == r的情况一并考虑
mid = l + r >> 1;
minx = Integer.MAX_VALUE;
idx = -1; //最小值索引
for(int i = 0; i < n; i++) {
int t = query(i, mid);
if(minx > t) {
minx = t;
idx = i;
}
}
if(mid == 0 || mid == n - 1 ||
mid > 0 && mid < n -2 && query(idx, mid - 1) > minx && query(idx, mid + 1) > minx)
return new int[]{idx, mid};
if(query(idx, mid - 1) < minx) r = mid;
else l = mid + 1;
}
return null;
}
}
方法2:
会被卡调用次数,但时间复杂度是一样的,只是常数项的差异。
遍历所有行,对每一行二分寻找当前行局部谷值,思路是:
1. 如果当前元素左边的值比它小,则左边一定存在局部谷值。
2. 右边同理。
3. 如果左右都比它小,当前元素就是局部谷值。
4. 找到局部谷值后,就可以和它上下的元素进行比较判断是不是全局谷值。
因此总的时间复杂度是O(nlogn)。
class Solution extends Getvalue {
public int[] getMinimumValue(int n) {
if (n == 1) return new int[]{0, 0};
for(int i = 0; i < n; i++) {
int l = 0, r = n - 1, mid = -1;
while(l < r) {
mid = l + r >> 1;
if(mid == 0 || mid == n -1) break;
int x = query(i,mid);
if(x > query(i, mid - 1)) r = mid;
else if(x > query(i, mid + 1)) l = mid + 1;
else
break;
}
mid = l + r >> 1;
if(check(i, mid, n)) return new int[]{i, mid};
}
return null;
}
boolean check(int x, int y, int n) {
int t = query(x, y);
if(x > 0 && t > query(x - 1, y) || x < n - 1 && t > query(x + 1, y))
return false;
return true;
}
}