タイトル説明
いくつかの要素の配列の先頭には、配列、我々は回転呼んで配列の最後に移動しました。出力回転最小の素子アレイの回転の入力配列の非降順。
問題解決のためのアイデア
回転アレイは、最小要素を含む新しい配列、および非減少ソートされた配列の半回転に分割することができます。配列の配列要素の新しい回転がそれによって(便宜上、ここでlog2N logN個書き込ま)O(logN個)のこのバイナリ性質のアルゴリズムの半分の時間複雑で問題の規模を減少させる、半元の配列です。
この時点で、問題は、非減少配列のアレイを、回転得られるかを判断するために半分に分割された2つの配列です。最後の要素に等しいより小さくなければならない配列の最初の要素を非減少知ることは容易です。
バイナリサーチアルゴリズムを変更することによって解決さ(L代表低いが、代表的な中間、H代表高いM):
- アレイ内NUMS [M] <= NUMS [H]、アレイ内の[M、H]で間隔アレイを非減少され、[L、Mは、H = M注文次いで、アレイ部を回転しているとき。
- L個の=のM + 1となるようそうでない場合、アレイ内の[M + 1、H]アレイは、回転部です。
public int minNumberInRotateArray(int[] nums) {
if (nums.length == 0)
return 0;
int l = 0, h = nums.length - 1;
while (l < h) {
int m = l + (h - l) / 2;
if (nums[m] <= nums[h])
h = m;
else
l = m + 1;
}
return nums[l];
}
配列要素が繰り返し可能な場合、特殊なケースが存在するであろう。NUMS [L] == NUMS [M] == NUMS溶液は、この時間間隔で決定することができない[H]、シーケンシャルサーチに切り替える必要があります。例えば、配列{1,1,1,0,1}、L、M及びHは、ポイントの数であり、この時間間隔は、どのような最小数の0分からないであろう。
public int minNumberInRotateArray(int[] nums) {
if (nums.length == 0)
return 0;
int l = 0, h = nums.length - 1;
while (l < h) {
int m = l + (h - l) / 2;
if (nums[l] == nums[m] && nums[m] == nums[h])
return minNumber(nums, l, h);
else if (nums[m] <= nums[h])
h = m;
else
l = m + 1;
}
return nums[l];
}
private int minNumber(int[] nums, int l, int h) {
for (int i = l; i < h; i++)
if (nums[i] > nums[i + 1])
return nums[i + 1];
return nums[l];
}
参照
CyC2018