记录一个遇到过的面试题,比较文明。。在一个有序数组中统计一个指定数字出现的次数。
遍历一遍就行了,O(n),但是作为面试答案肯定有点简单的过分了;
于是有个稍微复杂点的思路,因为是有序数组,可以先二分查找到指定元素,然后再向两侧扩展就好了,这样二分查找的时间复杂度是O(logn),然后在加上k(被查找的字符串长度),当母字符串很长,而被查找字符串比较短的时候,这个耗时会比遍历有优势。具体代码实现如下:
public class Main { public static void main(String[] args) { int[] sortArr2 = new int[]{1, 2, 2, 2, 3, 3}; num = 2; System.out.println(countNum(sortArr, num)); } /** * 统计指定数字在有序数组中出现的次数 * @param sortArr * @param num * @return */ private static int countNum(int[] sortArr, int num) { if (sortArr.length == 0) { return 0; } int count = 0; //查找到num第一次出现的位置 int pos = binarySearch(sortArr, 0, sortArr.length - 1, num); if (pos == -1) { return 0; } //向两侧顺序查找和num相等的数(因为数组是有序的) for (int i = pos; i > 0 && sortArr[i] == num; i --) { count ++; } for (int i = pos + 1; i < sortArr.length && sortArr[i] == num; i ++) { count ++; } return count; } /** * 二分查找 * @param sortArr * @param start * @param end * @param num * @return */ private static int binarySearch(int[] sortArr, int start, int end, int num) { if (start > end || (start == end && sortArr[start] != num)) { return -1; } int mid = (start + end) / 2; if (sortArr[mid] > num) { return findNum(sortArr, start, mid, num); } else if (sortArr[mid] < num) { return findNum(sortArr, mid + 1, end, num); } else { return mid; } } }