剑指offer面试题38 数字在排序数组中出现的次数

来源:互联网 发布:查看js绑定的事件 编辑:程序博客网 时间:2024/06/05 21:58

解题思路:

如果用顺序查找,这道题的时间复杂度是O(n),肯定不符合面试官的要求。看到排序数组,并且在里面查找一个数出现的次数,很自然的可以想到利用二分查找,因此这道题是二分查找的一个应用。假设待查找元素为k,如果要是能找到第一个k出现的位置和最后一个k出现的位置,两者相减在加上1即为k出现的次数。

具体来说,现在可以先对整个数组进行一次二分查找,记中间元素的索引为midIndex,对应的元素为midData。若midData和k相等,则比较midIndex前面一个数即midIndex-1指向的元素是否是元素k,若不是,则证明此时的midIndex为k第一次出现的位置,若是,则对midIndex之前的元素进行一次查找第一次k出现的位置(递归调用),直到找到k第一次出现的位置。对于查找k最后一次出现的位置,思路与上面类似。对整个数组进行二分查找,比较midIndex后面一个数即midIndex+1指向的元素是否为k,若不是,则证明此时的midIndex为k最后一次出现的位置,若是,则对midIndex之后的元素进行一次查找最后一个k出现的位置(递归调用),直到找到k最后一次出现的位置。

public class Solution {public int GetNumberOfK(int[] array, int k) {int number = 0;if (array != null && array.length != 0) {int first = getFirstK(array, 0, array.length - 1, k);int last = getLastK(array, 0, array.length - 1, k);if (first > -1 && last > -1) {number = last - first + 1;}}return number;}//在数组中找到k出现的第一个位置public int getFirstK(int[] array, int start, int end, int k) {if (start > end) {//此时表明未找到元素kreturn -1;}int midIndex = (start + end) / 2;int midData = array[midIndex];//利用二分查找if (midData == k) {//当中间元素与待查找元素相等时,判断前面一个元素是不是和k相等if (midIndex > 0 && array[midIndex - 1] != k || midIndex == 0) {//如果前一个元素不等于k,则此时midIndex是k出现第一次的位置return midIndex;} else {//如果前一个元素等于k,则此时需要在midIndex前面继续寻找第一个k出现的位置end = midIndex - 1;}} else if (midData > k) {//如果中间元素比k大,则k只可能出现在中间元素的前面,则下一次在数组的左半部分继续寻找kend = midIndex - 1;} else {//如果中间元素比k小,则k只可能出现在中间元素的后面,则下一次在数组的右半部分继续寻找kstart = midIndex + 1;}return getFirstK(array, start, end, k);}public int getLastK(int[] array, int start, int end, int k) {if (start > end) {//表明在数组中未找到元素kreturn -1;}int midIndex = (start + end) / 2;int midData = array[midIndex];//利用二分查找if (midData == k) {//当中间元素与待查找元素相等时,判断后面一个元素是不是和k相等if (midIndex < array.length - 1 && array[midIndex + 1] != k || midIndex == array.length - 1) {//如果前一个元素不等于k,则此时midIndex是k出现第一次的位置return midIndex;} else {//如果后一个元素等于k,则此时需要在midIndex后面继续寻找第一个k出现的位置start = midIndex + 1;}} else if (midData > k) {//如果中间元素比k大,则k只可能出现在中间元素的前面,则下一次在数组的左半部分继续寻找kend = midIndex - 1;} else {//如果中间元素比k小,则k只可能出现在中间元素的后面,则下一次在数组的右半部分继续寻找kstart = midIndex + 1;}return getLastK(array, start, end, k);}}


阅读全文
0 0