LeetCode No33. 搜尋旋轉排序陣列
題目
整數陣列 nums 按升序排列,陣列中的值 互不相同 。
在傳遞給函式之前,nums 在預先未知的某個下標 k(0 <= k < nums.length)上進行了 旋轉,使陣列變為 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下標 從 0 開始 計數)。例如, [0,1,2,4,5,6,7] 在下標 3 處經旋轉後可能變為 [4,5,6,7,0,1,2] 。
給你 旋轉後 的陣列 nums 和一個整數 target ,如果 nums 中存在這個目標值 target ,則返回它的下標,否則返回 -1 。
示例 1:
輸入:nums = [4,5,6,7,0,1,2], target = 0
輸出:4
示例 2:
輸入:nums = [4,5,6,7,0,1,2], target = 3
輸出:-1
示例 3:
輸入:nums = [1], target = 0
輸出:-1
提示:
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums 中的每個值都 獨一無二
題目資料保證 nums 在預先未知的某個下標上進行了旋轉
-10^4 <= target <= 10^4
進階:
你可以設計一個時間複雜度為 O(log n) 的解決方案嗎?
思路
暴力
其實題目說的這麼多,就是求陣列中target所在下標,暴力點直接一個遍歷就好
進階
暴力的解法沒有考慮到陣列本身的性質,陣列不管從哪個位置旋轉,最後形成的一定是兩個有序數列,這樣,我們就可以使用二分查詢去做了。我們可以在常規二分查詢的時候檢視當前 mid 為分割位置分割出來的兩個部分 [l, mid] 和 [mid + 1, r] 哪個部分是有序的,並根據有序的那個部分確定我們該如何改變二分查詢的上下界,因為我們能夠根據有序的那部分判斷出 target 在不在這個部分:
如果 [l, mid - 1] 是有序陣列,且 target 的大小滿足 [nums[l],nums[mid]),則我們應該將搜尋範圍縮小至 [l, mid - 1],否則在 [mid + 1, r] 中尋找。
如果 [mid, r] 是有序陣列,且 target 的大小滿足 (nums[mid+1],nums[r]],則我們應該將搜尋範圍縮小至 [mid + 1, r],否則在 [l, mid - 1] 中尋找。
AC程式碼
暴力
點選檢視程式碼
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
for(int i=0; i<len; i++) {
if( nums[i] == target ) {
return i;
}
}
return -1;
}
}
進階
點選檢視程式碼
class Solution {
public int search(int[] nums, int target) {
int len=nums.length;
if(len==0 ) {
return -1;
}
if( len==1 ) {
return nums[0]==target?0:-1;
}
int left = 0;
int rigth = len-1;
while( left<=rigth ) {
int mid = (left+rigth)/2;
if (nums[mid] == target) {
return mid;
}
if( nums[0]<=nums[mid] ) {
if( nums[0]<=target && target<nums[mid] ) {
rigth = mid -1;
} else {
left = mid + 1;
}
} else {
if( target<=nums[len-1] && target>nums[mid] ) {
left = mid + 1;
} else {
rigth = mid - 1;
}
}
}
return -1;
}
}