記錄一個遇到過的面試題,比較文明。。在一個有序數組中統計一個指定數字出現的次數。
遍歷一遍就行了,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; } } }
