题目描述
统计一个数字在排序数组中出现的次数。java
方法一
最简单的方法就是遍历整个数组。没什么好说的,很low.面试
/** * 方法一 * @param array * @param k * @return */ public int GetNumberOfK(int [] array , int k) { if(array == null || array.length == 0) { return 0; } int times = 0; for (int i = 0; i < array.length; i++) { if(array[i] == k) { ++times; } } return times; }
方法二
数组是有序的,咱们能够利用二分查找。直观的一个思路就是经过二分查找得到一个k在数组中的下标,而后顺序的在k的前面和后面寻找和k相等的数。数组
/** * 方法二 */ public int GetNumberOfK_2(int [] array , int k) { if(array == null || array.length == 0) { return 0; } int low = 0, high = array.length - 1, mid = 0, times = 0; while(low <= high) { mid = (low + high) / 2; if(k < array[mid]) { high = mid - 1; } else if(k > array[mid]) { low = mid + 1; } else { times = 1; break; } } for (low = mid - 1; (low >= 0) && (array[low] == k); low--) { times += 1; } for (low = mid + 1; (low < array.length) && (array[low] == k); low++) { times += 1; } return times; }
可是极可能面试官还不满意,还想要更快的方法。spa
方法三
经过二分查找得到数组中第一个k的下标和最后一个k的下标,而后下标相减就是出现的次数。思路是经过二分找到一个k,先判断这个数字是否是第一个k,若是中间数字的前面一个数字不是k,那么此时中间数字恰好就是第一个k,若是中间数字的前面一个数字也是k,那么第一个k确定在数组的前半段,继续二分,这是递归的过程。
寻找第一个k下标的方法(递归):code
private int FetFirstK(int[] elem, int k, int start, int end) { if(start > end) { return -1; } int mid = (start + end) / 2; if(elem[mid] > k) { return FetFirstK(elem, k, start, mid - 1); } else if(elem[mid] < k) { return FetFirstK(elem, k, mid + 1, end); } else if(mid - 1 >= 0 && elem[mid - 1] == k) { return FetFirstK(elem, k, start, mid - 1); } else { return mid; } }
寻找最后一个k的下标的方法(非递归):排序
private int FetLastK(int[] elem, int k, int start, int end) { int mid = (start + end) / 2; while(start <= end) { if(elem[mid] > k) { end = mid - 1; } else if(elem[mid] < k) { start = mid + 1; } else if(mid + 1 <elem.length && elem[mid + 1] == k) { start = mid + 1; } else { return mid; } mid = (start + end) / 2; } return -1; }
主方法:递归
/** * 方法三 * @param array * @param k * @return */ public int GetNumberOfK_3(int [] array , int k) { if(array == null || array.length == 0) { return 0; } int firstK = FetFirstK(array, k, 0, array.length - 1); int lastK = FetLastK(array, k, 0, array.length - 1); if(firstK != -1 && lastK != -1) { return lastK - firstK + 1; } return 0; }
方法四
由于数组中都是整数,因此能够稍微变一下,不是搜索k的两个位置,而是搜索k-0.5和k+0.5这两个数应该插入的位置,而后相减便可。ast
/** * 方法四 * @param array * @param k * @return */ public int GetNumberOfK_4(int [] array , int k) { if(array == null || array.length == 0) { return 0; } return biSearch(array, k + 0.5) - biSearch(array, k - 0.5); } private int biSearch(int[] elem, double num) { int start = 0, end = elem.length - 1, mid = (start + end) / 2; while(start <= end) { if(elem[mid] < num) { start = mid + 1; } else if(elem[mid] > num) { end = mid - 1; } mid = (start + end) / 2; } return start; }