タイトル:LeetCode(33)
昇順でソートされた配列が、事前に不明な特定のポイントで回転するとします。
(たとえば、配列[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]、ターゲット= 0
出力:4
例2:
入力:nums = [4,5,6,7,0,1,2 ]、ターゲット= 3
出力:-1
問題の解決策:問題
の意味は、回転配列で特定の値を検索できるようにすることです。存在する場合は、この値の対応する座標を返します。存在しない場合は、-1を直接返します。よく考えてみると、実際には二分探索の変形であることがわかります。二分探索を考えてみましょう。ただし、この質問の難しさは、元の配列がどこで回転されているかわからないことです。分析するタイトル。配列[01 2 4 5 6 7]には、次の7つの回転方法があります。
[0 1 2 4 5 6 7]
[7 0 1 2 4 5 6]
[6 7 0 1 2 4 5]
[5 6 7 0 1 2 4]
[4 5 6 7 0 1 2]
[2 4 5 6 7 0 1]
[1 2 4 5 6 7 0]
観測結果:中央値が右端よりも大きい場合は左側が順番になり、中央値が右端よりも小さい場合は右側が順番になります。したがって、順序付けられた半分の最初と最後の2つの配列を使用して、ターゲット値がこの領域にあるかどうかを判断するだけで、どちらの半分を保持するかを判断できます。
int rotatedBinarySearch(int[] arr, int target){
// 最左侧元素下标
int left = 0;
// 最右侧元素下标
int right = arr.length - 1;
while(left <= right){
// 中间元素下标
int mid = left + (right - left) / 2;
if(arr[mid] == target){
return mid;
}
// 情况1:如果中间元素在旋转点左侧
if(arr[mid] >= arr[left]){
//target 如果位于中间元素的左侧
if(arr[mid] > target && target >= arr[left]){
right = mid - 1;
}else{
left = mid + 1;
}
}
// 情况2:中间元素在旋转点的右侧
else{
// target 如果位于中间元素的右侧
if(arr[mid] < target && target <= arr[right]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return -1;
}