今天我沒事幹,決定把好多天沒寫的Leetcode看一下,看到了33題,題目如下:
給定一個經過“旋轉變換”的有序數組還有一個你要查找的目標數字,給出目標數字在數組中的下標,不存在則返回-1。例如給定{4, 5, 6, 7, 0, 1, 2, 3},6,函數返回值就應該是2。
題目相信大家都能看懂,也都能想到一定的方法。那麼接下來就一起探討一下吧。
第一種方法:
最容易想到的也一定就是最笨的,那就是直接遍歷這個數組,這當然是可行的,下面給出對應的Java代碼:
public class Solution {
public int search(int[] nums, int target) {
// 使用Java一定要注意判斷是否爲空指針
if (nums == null)return -1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target) return i;
}
return -1;
}
}
嗯,結果還不錯,順利通過所有的樣例,排名超過87%,(lll¬ω¬)這麼暴力的嗎?難道大部分人都是直接遍歷的。。。
第二種方法:
嗯,我想大家都應該理解出題人絕不是想讓我們暴力搜索的,所以自然看到題目中的有序,就應該想到是二分搜索啦,那麼這個題的話要怎麼使用二分搜索呢?由題目中的樣例可以推測我們是要把數組分爲兩部分看的,判斷方法就需要改進了。
首先判斷mid處的值是不是target,是的話可以直接返回,不是的話就有點麻煩了,判斷mid是否大於最左端處的值,大於說明這個mid是在左端的半邊的,這個時候如果target夾在兩者中間時就只需要r = mid - 1就是了,沒有在其中的話說明不是在mid左半邊的l = mid + 1,下面的就同理了。
看代碼:
public class Solution {
public int search(int[] nums, int target) {
// 使用Java一定要注意判斷是否爲空指針
if (nums == null)return -1;
int l = 0, r = nums.length - 1;
int mid = 0;
while (l <= r) {
mid = (r + l) / 2;//不管那麼多了
if (nums[mid] == target) {
return mid;
}
if (nums[mid] >= nums[l]) {
if (target < nums[mid]
&& target >= nums[l]) {
r = mid - 1;
}
else {
l = mid + 1;
}
}
if (nums[mid] <= nums[r]) {
if (target > nums[mid]
&& target <= nums[r]) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
}
return -1;
}
}