1.搜索旋轉排序數組
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。
搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。
你可以假設數組中不存在重複的元素。
你的算法時間複雜度必須是 O(log n) 級別。
示例 1:
輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4
示例 2:
輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1
解法:
- 找到旋轉的下標 rotation_index ,也就是數組中最小的元素。二分查找在這裏可以派上用場。
- 在選中的數組區域中再次使用二分查找。
public int search(int[] nums, int target) {
if(nums.length == 0) return -1;
if(nums.length == 1){
return nums[0] == target ? 0:-1;
}
int rotate_index = find_rotate_index(nums,0,nums.length-1);
if(nums[rotate_index] == target){
return rotate_index;
}
if(rotate_index == 0){
return binarySearch(nums,0,nums.length-1,target);
}
if(nums[0] > target){
return binarySearch(nums,rotate_index,nums.length-1,target);
}
return binarySearch(nums,0,rotate_index-1,target);
}
public int find_rotate_index(int[] nums,int lo, int hi) {
//沒有旋轉
if(nums[lo] < nums[hi]){
return 0;
}
while(lo <= hi){
int mid=(lo+hi)/2;
if(nums[mid+1] < nums[mid]){
return mid+1;
}else{
if(nums[mid] < nums[lo]){
hi = mid-1;
}else{
lo = mid+1;
}
}
}
return 0;
}
//二分查找
public int binarySearch(int[] nums,int lo, int hi,int target) {
while(lo <= hi){
int mid=(lo+hi)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] > target){
hi = mid-1;
}else {
lo = mid+1;
}
}
return -1;
}
2.搜索旋轉排序數組 II
上題的延伸題,本題中的 nums 可能包含重複元素。
示例 1:
輸入: nums = [2,5,6,0,0,1,2], target = 0
輸出: true
示例 2:
輸入: nums = [2,5,6,0,0,1,2], target = 3
輸出: false
解法:
與上題的區別是在尋找旋轉下標時,如果是在重複元素處旋轉的,那麼只能遍歷尋找。
class Solution {
public boolean search(int[] nums, int target) {
if(nums.length == 0) return false;
if(nums.length == 1){
return nums[0] == target ? true:false;
}
int rotate_index = find_rotate_index(nums,0,nums.length-1);
if(nums[rotate_index] == target){
return true;
}
if(rotate_index == 0){
return binarySearch(nums,0,nums.length-1,target);
}
if(nums[0] > target){
return binarySearch(nums,rotate_index,nums.length-1,target);
}
return binarySearch(nums,0,rotate_index-1,target);
}
public int find_rotate_index(int[] nums,int lo, int hi) {
//沒有旋轉
if(nums[lo] < nums[hi]){
return 0;
}
while(lo <= hi){
int mid=(lo+hi)/2;
//在重複元素處旋轉的情況下,遍歷處理
if(nums[mid] == nums[lo] && nums[mid] == nums[hi]){
for(int i = 1;i < nums.length;i++){
if(nums[i] < nums[i-1]){
return i;
}
}
return 0;
}
if(nums[mid+1] < nums[mid]){
return mid+1;
}else{
if(nums[mid] < nums[lo]){
hi = mid-1;
}else{
lo = mid+1;
}
}
}
return 0;
}
//二分查找
public boolean binarySearch(int[] nums,int lo, int hi,int target) {
while(lo <= hi){
int mid=(lo+hi)/2;
if(nums[mid] == target){
return true;
}else if(nums[mid] > target){
hi = mid-1;
}else {
lo = mid+1;
}
}
return false;
}
}