コード:
class Solution {
public int findMin(int[] nums) {
int left=0,right=nums.length-1;
int refer=nums[right];
while (left<right){
int mid=left+(right-left)/2;
if(nums[mid]>refer){
left=mid+1;
}else {
right=mid;
}
}
return nums[left];
}
}
答え:
質問の意味から、渡されるパラメータは 1、2、3、4、5 を回転させて得られる 3、4、5、1、2 のように回転増加する配列であることがわかります。この回転した配列は、3、4、5、1、2 を例に挙げると、写真を通してはっきりと見ることができます。
回転後の増分配列のほとんどがこのような構造になっていることがわかります。データを 2 つの区間に分割し、得られる答えは下の区間の左側の境界にあります。
配列の最後のデータを参照として使用して、配列内の数値 nums[i] を選択することができます。この数値は、上部と下部の区間に位置する場合があります。
(1). nums[ i ] > を参照する場合は、数値が上の範囲にあることを意味するので、添字 i が指すデータと左側のデータを大胆に削除できます。
(2). nums[i] <= を参照する場合、その数値が次の区間にあることを意味するので、添字 i の右側のデータを大胆に削除できます (ただし、添字 i が正しいかどうかはわかりません)はまさに必要なデータを指しているため、下付き文字 i が指しているデータを削除することはできません)
上記の分析により、質問には 2 段階の性質があることが判明したため、二分法で問題を解決できます。
例として nums = 3, 4, 5, 1, 2 を使用し、L および R ポインタを使用して配列の両端を指します (mid = left+(right-left)/2= 2)。このとき、Rポインタは配列の末尾を指します。データの一部を参照値として記録できます (ref = nums[ R ] = 2)。
この時点では、nums[mid] = 5 > を参照しているため、上記の区間で、mid ポインタとmid ポインタの左側のデータを大胆に削除できます (L = Mid+1 とします)。
3 4 5 1 2
L ミッド R
中間の値を計算します (mid = 3)。この時点では、nums[mid] = 1 < であるため、次の区間では、mid の右側のデータを大胆に削除し、R = Mid とします。
3 4 5 1 2
L R
半ば
L ポインターと R ポインターが一致すると、次の区間の左側の境界を見つけて、直接 nums[L] を返します。
3 4 5 1 2
L
R