コード:
class Solution {
public int peakIndexInMountainArray(int[] arr) {
int left=0,right=arr.length-1;
while (left<right){
int mid=left+(right-left+1)/2;
if(arr[mid]>arr[mid-1]){
left=mid;
}else {
right=mid-1;
}
}
return left;
}
}
答え:
質問の要件を簡単に分析してみましょう。まず、質問で与えられる情報は次のとおりです。
1. 山の配列の長さ > = 3。これは、各配列に頂点が存在する必要があることを意味します。
2. 山の配列は整数で構成されます
3. arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
を満たす添字を見つける必要があります。i
したがって、配列は次の構造になります。
たとえば、配列 arr =[1,2,3,2,1] の場合、探している頂点は 3、添え字は 2 です。
上記の配列を分析します。配列を 2 つの区間に分割できます。[1, 2, 3] は増加する区間、[2, 1] は減少する区間です。図の分割は次のようになります。
この除算により、探しているデータは増加する間隔の正しい境界です。配列内の数値 arr[i] をランダムに選択すると、arr[i] > arr[i-1] の場合、 ]、数値が増加範囲にあることを意味します。数値の左側のデータを大胆に除外できます ( ただし、数値を除外することはできません、なぜなら、私たちが得たい答えは「間隔が増加する中で、その数値が私たちが望む答えと正確に一致しているかどうかはわからないからです」
arr[ i ] < arr[ i-1 ] の場合、数値が減少範囲にあることを意味し、数値と数値の右側のデータを大胆に除外できます。
上記の分析を通じて、この質問には 2 段階の性質があることがわかったので、この問題を解決するために二分法を使用できます。
arr =[1,2,3,2,1]の例も同様です
L および R ポインタを左右の境界に向けて、mid = L + (R- L+1)/2 = 3 を計算します。arr[mid] > arr[mid -1] であるため、mid が指す値はは増加範囲内にあり、L=mid とします。
1 2 3 2 1
L ミッド R
Mid = 3 を計算します。この時点では arr[mid]
1 2 3 2 1
L ミッド R
LポインタとRポインタが一致した場合は、条件を満たす値が見つかったことを意味し、Lポインタが指す位置を返すことができます。
1 2 3 2 1
L
R