关于折半查找中的几个注意点.
Version 1:
public static <T extends Comparable<? super T>> int binSearch(T[] arr, T element) { int length = arr.length; int middle = length / 2; int index; if (length == 0) { return -1; } if (arr[middle].compareTo(element) == 0) { index = middle; } else if (arr[middle].compareTo(element) < 0) { index = middle + 1 + binSearch(Arrays.copyOfRange(arr, middle + 1, length), element); } else { index = binSearch(Arrays.copyOfRange(arr, 0, middle), element); } return index; }
要保证接口为binSearch(array, target),所以此处使用了Arrays.copyOfRange()--导致造成了额外的空间消耗(创建新的数组)。
Version 2:
// 注意这种切换接口的方式 public static <T extends Comparable<? super T>> int binSearch_JDK(T[] arr, T element) { //With Recursion return binSearch_JDK(arr, 0, arr.length - 1, element); } // With Recursion public static <T extends Comparable<? super T>> int binSearch_JDK(T[] arr, int start, int end, T element) { if(start > end){ return -1; } int middle = (start + end) / 2; if(arr[middle].compareTo(element) == 0){ return middle; }else if(arr[middle].compareTo(element) < 0){ return binSearch_JDK(arr, middle + 1, end, element); }else{ return binSearch_JDK(arr, 0, middle - 1, element); } }
保证了接口原型不变,而且没有额外的空间消耗(创建新的数组)。注意这种切换接口的方式。
Version 3:
// 注意这种切换接口的方式 public static <T extends Comparable<? super T>> int binSearch_JDK(T[] arr, T element) { //Without Recursion return binarySearch(arr, 0, arr.length - 1, element); } // JDK SOURCE CODE jdk没有使用泛型,而是直接使用了long // 能不用递归就不要用 public static <T extends Comparable<? super T>> int binarySearch(T[] arr, int start, int end, T element) { int middle = start; while(start <= end){ //middle = (start + end) / 2; middle = (start + end) >>> 1; if(arr[middle].compareTo(element) == 0){ return middle; }else if(arr[middle].compareTo(element) < 0){ start = middle + 1; }else{ end = middle - 1; } } return -1; }
这种方法相对于前2种方法要好很多:接口原型不变,而且没有额外的空间消耗(创建新的数组)并且没有使用递归。