整数の配列が与えられたら、極小値を見つけます。要素A [i]は、A [i-1]> A [i]およびA [i] <A [i + 1]の場合、i = 1 ... n-2の場合、極小値として定義されます。境界要素の場合、数値は隣接する数値よりも小さくなければなりません。
局所最小値が1つしかない場合は、修正されたバイナリ検索で解決できます。しかし、配列に複数の極小値が存在することがわかっている場合、O(log n)
時間で解決できますか?
配列要素が明確であることが保証されていない場合、O(log n)時間でこれを行うことはできません。その理由は次のとおりです。n> 1の値がすべて同じである配列があるとします。この場合、隣接する要素よりも小さい要素はないため、どの要素も局所的な最小値にできません。ただし、すべての値が同じであることを判断するには、すべての配列要素を確認する必要があります。これには、O(n)時間を使用します。O(n) time、必ずしもすべての配列要素を見ることができるわけではありません。
一方、配列要素が明確であることが保証されている場合、次の観測を使用してO(log n)時間でこれを解決できます。
したがって、次の再帰的アルゴリズムを構築できます。
これには再帰関係があることに注意してください
T(1)≤1
T(2)≤1
T(n)≤T(n/2)+ 1
マスター定理を使用すると、必要に応じてこのアルゴリズムが時間O(log n)で実行されることを示すことができます。
お役に立てれば!
また、このアルゴリズムが機能するのは、隣接する要素よりも小さい場合に配列のエッジがローカルミニマムとしてカウントされる場合のみであることに注意してください。
極小値の数は_n/2
_になります。すべてをO(log n)
時間で列挙することはできません。
分割統治アルゴリズムを使用します。 m = n/2とし、値A [m](つまり、配列の中央の要素)を調べます。
ケース1:A [m-1] <A [m]。次に、配列の左半分にローカルミニマムが含まれている必要があるため、左半分を再帰します。これは矛盾によって示すことができます:A [i]は各0≤i <mの局所最小値ではないと仮定します。この場合、A [m-1]は局所的な最小値ではなく、A [m-2] <A [m-1]であることを意味します。同様に、A [m -3] <A [m -2]。このように続けて、A [0] <A [1]を取得します。しかし、A [0]は最初の仮定に反して、極小値です。
ケース2:A [m + 1]> A [m]。その場合、配列の右半分には局所的な最小値が含まれている必要があるため、右半分で再帰します。これは、ケース1と対称的です。
ケース3:A [m − 1]> A [m]およびA [m + 1] <A [m]。その場合、A [m]は極小値なので、それを返します。実行時間の繰り返しはT(n) = T(n/2) +Θ(1)、これによりT(n) =Θ(log n)。
実際、以前のアルゴリズムを変更して、O(log n)時間ですべての最大値を取得できます。提供されたすべての入力に対してうまく機能することをテストしました。あなたのフィードバックを教えてください
public class LocalMaximas {
@Test
public void test () {
System.out.println("maximas: please modify code to handle if array size is <= 2");
int []a = {5,8,10,25,6,3,44,51,55,56,57,58,34,5,59,2};
localMaximas(a);
int []b = {9,7,2,8,5,6,3,4, 2}; //9,8,6,4
localMaximas(b);
int [] c= {15, 13, 12, 18, 19, 20, 7, 6, 5, 4, 3, 2, 1};//15,20
localMaximas(c);
}
public void localMaximas (int [] a) {
System.out.println("\n\n");
if(isMaxima(a,0)) {
System.out.println(a[0]);
}
if(isMaxima(a,a.length-1)) {
System.out.println(a[a.length-1]);
}
localMaximas(a,0,a.length-1);
}
int localMaximas(int []a,int low, int high) {
int mid = (low+high)/2;
if(high-low > 3) { // more than 4 items in currently divided array
if(isMaxima(a,mid)) {
System.out.println(a[mid]);
}
localMaximas(a,low, mid);
localMaximas(a,mid, high);
}
else if(high-low == 3){ //exactly 4 items in currently divided array
localMaximas(a,low, mid+1);
localMaximas(a,mid, high);
}
else if((high-low == 2) && (isMaxima(a,low+1))) {
System.out.println(a[low+1]);
}
return 0;
}
int maxof(int []a, int i, int j) {
if(a[i] <a[j]) {
return j;
}
else {
return i;
}
}
boolean isMaxima(int []a ,int mid) {
if(mid == 0) {
if(maxof(a, mid, mid+1) == mid) {
return true;
}
else {
return false;
}
}
else if(mid==a.length-1) {
if(maxof(a,mid,mid-1) == mid) {
return true;
}
else {
return false;
}
}
else {
if((maxof(a, mid, mid+1) == mid) && (maxof(a, mid, mid-1) == mid)) {
return true;
}
else {
return false;
}
}
}
}
元の質問は完全ではありません。
配列内の極小値を見つける !で完全な質問と詳細な説明を見つけました。 -私のブログではありません
最初の2つの数値が減少し、最後の2つの数値が増加する一意の整数の配列が与えられた場合、配列内の極小値を見つけます。配列内の数値は、左右の数値よりも小さい場合、ローカルミニマムと呼ばれます。
たとえば、配列9,7,2,8,5,6,3,4では、2はその左と右の数字7および8よりも小さいため、極小値です。同様に5は8の間であるため、もう1つの極小値ですおよび6、両方とも5より大きい。
極小値のいずれかを見つける必要があります。
この配列ではアルゴリズムは機能しません
15, 13, 12, 18, 19, 20, 7, 6, 5, 4, 3, 2, 1
ここで、ローカルミニマムは12.です。しかし、7である中間要素をチェックすると、アルゴリズムは左半分(ミニマムがある)を破棄し、右半分をチェックインします。したがって、動作しません
配列にA [1]≥A [2]かつA [n − 1]≤A [n]という特別なプロパティがある場合にのみ機能すると思います。
O(log n)で機能するソリューションを次に示します。基本的に、これはマージソートアプローチ(分割および征服)で機能します。
public class LocalMaxima {
int []a = {5,8,10,25,6,3,44,51,55,56,57,58,34,5,59};
@Test
public void localMaxima () {
System.out.println((a[localMaxima(0,a.length-1)]));
}
int localMaxima(int low, int high) {
if(high-low > 2) {
int mid = (low+high)/2;
return maxof(localMaxima(low,mid),localMaxima(mid+1, high));
}
else if(high-low == 1) {
return maxof(high,low);
}
else if(high-low == 0) {
return high;
}
if(high-low == 2) {
return maxof(maxof(low, high),low+1);
}
return 0;
}
int maxof(int i, int j) {
if(a[i] <a[j]) {
return j;
}
else {
return i;
}
}
}