私は大学の休みを利用してJava=コーディングアルゴリズムを通じて実践しています。私がコーディングしたアルゴリズムの1つはバイナリ検索でした:
public class BinarySearch {
private static int list[] = {3, 6, 7, 8, 9, 10};
public static void main(String[] args) {
BinarySearch b = new BinarySearch();
b.binarySearch(list);
}
public void binarySearch(int[] args) {
System.out.println("Binary search.");
int upperBound = args.length;
int lowerBound = 1;
int midpoint = (upperBound + lowerBound) / 2;
int difference = upperBound - lowerBound;
int search = 7;
for (int i = 0; i < args.length; i++) {
if (search < args[midpoint - 1] && difference != 1) {
upperBound = midpoint - 1;
midpoint = upperBound / 2;
} else if (search > args[midpoint - 1] && difference != 1) {
lowerBound = midpoint + 1;
midpoint = (lowerBound + upperBound) / 2;
} else if (search == args[midpoint - 1]) {
midpoint = midpoint - 1;
System.out.println("We found " + search + " at position " + midpoint + " in the list.");
i = args.length;
} else {
System.out.println("We couldn't find " + search + " in the list.");
i = args.length;
}
}
}
}
私は本当に、よりクリーンで効率的なバイナリ検索アルゴリズムを記述できるようになりたいと思っています。これは、私がコーディングしたものの代替です。私が理解している数値で階乗を行うときなど、再帰がどのように使用されるかの例を見てきました。しかし、この複雑さの何かをコーディングするとき、私はそれを私の利点にどのように使用するかについて混乱しています。したがって、私の質問は、バイナリサーチアルゴリズムをコーディングするときに再帰をどのように適用するかです。また、バイナリ検索を考慮しないものである必要がある場合でも、私の再帰スキルを完成させるためのヒントがあれば、遠慮なく投稿してください。
本当に再帰を使用したい場合は、これで十分です。
public static int binarySearch(int[] a, int target) {
return binarySearch(a, 0, a.length-1, target);
}
public static int binarySearch(int[] a, int start, int end, int target) {
int middle = (start + end) / 2;
if(end < start) {
return -1;
}
if(target==a[middle]) {
return middle;
} else if(target<a[middle]) {
return binarySearch(a, start, middle - 1, target);
} else {
return binarySearch(a, middle + 1, end, target);
}
}
バイナリ検索を行う簡単な方法を次に示します。
public static int binarySearch(int intToSearch, int[] sortedArray) {
int lower = 0;
int upper = sortedArray.length - 1;
while (lower <= upper) {
int mid = lower + (upper - lower) / 2;
if(intToSearch < sortedArray[mid])
upper = mid - 1;
else if (intToSearch > sortedArray[mid])
lower = mid + 1;
else
return mid;
}
return -1; // Returns -1 if no match is found
}
可能な例は次のとおりです。
// need extra "helper" method, feed in params
public int binarySearch(int[] a, int x) {
return binarySearch(a, x, 0, a.length - 1);
}
// need extra low and high parameters
private int binarySearch(int[ ] a, int x,
int low, int high) {
if (low > high) return -1;
int mid = (low + high)/2;
if (a[mid] == x) return mid;
else if (a[mid] < x)
return binarySearch(a, x, mid+1, high);
else // last possibility: a[mid] > x
return binarySearch(a, x, low, mid-1);
}
ここでは、Cバイナリ検索で、再帰ありとなしでチェックできます。
ソース: http://www.cs.utsa.edu/~wagner/CS3343/recursion/binsearch.html
以下は here から抽出されたコードサンプルです。
public class BinarySearch {
public boolean find(int[] sortedValues, int value) {
return search(sortedValues, value, 0, sortedValues.length - 1);
}
private boolean search(int[] sorted, int value, int leftIndex, int rightIndex) {
// 1. index check
if (leftIndex > rightIndex) {
return false;
}
// 2. middle index
int middle = (rightIndex + leftIndex) / 2;
// 3. recursive invoke
if (sorted[middle] > value) {
return search(sorted, value, leftIndex, middle - 1);
} else if (sorted[middle] < value) {
return search(sorted, value, middle + 1, rightIndex);
} else {
return true;
}
}
}
上記のバイナリ検索実装に対する以下のテストケースの実装は、リファレンス link でも確認できます。
1. shouldReturnFalseIfArrayIsEmpty()
2. shouldReturnFalseIfNotFoundInSortedOddArray()
3. shouldReturnFalseIfNotFoundInSortedEvenArray()
4. shouldReturnTrueIfFoundAsFirstInSortedArray()
5. shouldReturnTrueIfFoundAtEndInSortedArray()
6. shouldReturnTrueIfFoundInMiddleInSortedArray()
7. shouldReturnTrueIfFoundAnywhereInSortedArray()
8. shouldReturnFalseIfNotFoundInSortedArray()
これは再帰を行う別の方法です:
int[] n = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
@Test
public void testRecursiveSolution() {
Assert.assertEquals(0, recursiveBinarySearch(1,n));
Assert.assertEquals(15, recursiveBinarySearch(16,n));
Assert.assertEquals(14, recursiveBinarySearch(15,n));
Assert.assertEquals(13, recursiveBinarySearch(14,n));
Assert.assertEquals(12, recursiveBinarySearch(13,n));
Assert.assertEquals(11, recursiveBinarySearch(12,n));
Assert.assertEquals(10, recursiveBinarySearch(11,n));
Assert.assertEquals(9, recursiveBinarySearch(10,n));
Assert.assertEquals(-1, recursiveBinarySearch(100,n));
}
private int recursiveBinarySearch(int n, int[] array) {
if(array.length==1) {
if(array[0]==n) {
return 0;
} else {
return -1;
}
} else {
int mid = (array.length-1)/2;
if(array[mid]==n) {
return mid;
} else if(array[mid]>n) {
return recursiveBinarySearch(n, Arrays.copyOfRange(array, 0, mid));
} else {
int returnIndex = recursiveBinarySearch(n, Arrays.copyOfRange(array, mid+1, array.length));
if(returnIndex>=0) {
return returnIndex+mid+1;
} else {
return returnIndex;
}
}
}
}
ここにあなたが行くはずのアルゴリズムがあります。メソッドシグネチャを次のようにします。
public boolean binarysearchRecursion(Array, begin_index,end_index, search_element)
false
を返します。mid_element
を入力配列に使用します。search_element
はこれに等しいmid_element
。 YESの場合はtrue
を返しますmid_element
> search_element
forでメソッドを呼び出すrange 0 - mid
mid_element
<search_element
範囲を指定してメソッドを呼び出すmid+1 - Length_of_Array
また、@ DwBのコメントで述べたように、ループを使用して処理を完了させることをお勧めします。一部の問題は本質的に再帰的です(バイナリツリーの問題と同様)。しかし、これはそれらの1つではありません。
探している値が見つからない場合のブレーク条件付きの再帰BinarySearch
public interface Searcher{
public int search(int [] data, int target, int low, int high);
}
実装
public class BinarySearch implements Searcher {
public int search(int[] data, int target, int low, int high) {
//The return variable
int retorno = -1;
if(low > high) return retorno;
int middle = (high + low)/2;
if(target == data[middle]){
retorno = data[middle];
}else if(target < data[middle] && (middle - 1 != high)){
//the (middle - 1 != high) avoids beeing locked inside a never ending recursion loop
retorno = search(data, target, low, middle - 1);
}else if(target > data[middle] && (middle - 1 != low)){
//the (middle - 1 != low) avoids beeing locked inside a never ending recursion loop
retorno = search(data, target, middle - 1, high);
}else if(middle - 1 == low || middle - 1 == high){
//Break condition if you can not find the desired balue
retorno = -1;
}
return retorno;
}
}
これはインデックスを返しませんが、少なくともコレクションに何かがあるという「はい」または「いいえ」の考えを返します。
public static boolean recursive(int[] input, int valueToFind) {
if (input.length == 0) {
return false;
}
int mid = input.length / 2;
if (input[mid] == valueToFind) {
return true;
} else if (input[mid] > valueToFind) {
int[] smallerInput = Arrays.copyOfRange(input, 0, mid);
return recursive(smallerInput, valueToFind);
} else if (input[mid] < valueToFind) {
int[] smallerInput = Arrays.copyOfRange(input, mid+1, input.length);
return recursive(smallerInput, valueToFind);
}
return false;
}