一个没有重复值的有序数组,把后半段,放在前半段。比如[4, 5, 6, 1, 2, 3],请返回某个值的下标。
我的第一反应是寻找出这个数组的断点(最大值),这样做再做两次二分搜索就可以了。
这样这个问题就化归为 寻找最大值 + 二分搜索了。
如果不用这种算法呢?能不能直接查找了。
首先这个这种数组要分三种情况。
- arr[m] = key, 直接返回m
- arr[m] >= arr[p], 然后再比较arr[m] , arr[p], arr[q]
- arr[m] < arr[q],然后再比较arr[m] , arr[p], arr[q]
public int find2(int[] arr, final int key) {
if (arr == null || arr.length == 0) {
return -1;
}
int p = 0;
int q = arr.length - 1;
while (p <= q) {
int m = p + (q - p) / 2;
if (arr[m] == key) {
return m;
}
if (arr[m] >= arr[p]) {
if (key < arr[m] && key >= arr[p]) {
q = m - 1;
} else {
p = m + 1;
}
} else {
if (key > arr[m] && key <= arr[q]) {
p = m + 1;
} else {
q = m - 1;
}
}
}
return -1;
}
刚拿到这道题目的时候,自然会想到二分搜索,想利用以前的经验去解决。但是如果思维囿于以前的经验,则不可能解决问题。因为新的问题需要新的手段,需要在以前的思路上更进一步。这道题目用到了两次分类讨论,所以一共有四种情况。
很遗憾,自己当时没有做出这道题,因为没有厘清这几种情况。
另外测试的话,一定要重点测试特殊情况,长度是1和2的数组。(这是折半的最小单元)
如果一般情况没有问题,特殊情况没有问题,这段代码大概率没问题。
网友评论