【二分法】数字在升序数组中出现的次数

题目描述

统计一个数字在升序数组中出现的次数。
示例1
输入
[1,2,3,3,3,3,4,5], 3
返回值
4


看到数组是有序的,并且是查找,应该想到用二分法,最简单的方法是用二分法找到该数,然后以它为中心向左右两边搜索计数

public class Solution {
    
    
    public int GetNumberOfK(int[] array, int k) {
    
    
        // 二分查找
        int low = 0, high = array.length - 1, middle;
        int count = 0;
        while (low <= high) {
    
    
            middle = (low + high) / 2;
            if (k > array[middle])
                low = middle + 1;
            else if (k < array[middle])
                high = middle - 1;
            else {
    
    
                // find k
                int i = middle;
                while (i >= 0 && array[i] == k) {
    
    
                    count++;
                    i--;
                }
                i = middle + 1;
                while (i < array.length && array[i] == k) {
    
    
                    count++;
                    i++;
                }
                break;
            }
        }
        return count;
    }
}

优化方法是利用二分法找到k第一次出现和最后一次出现的位置,相减即可得到k出现的次数。为了得到第一次出现的位置和最后一次出现的位置,需要稍微改写二分法。

第一次出现的位置
当array[middle] == k 时,令high = middle - 1,继续往前找第一个出现的位置,最后返回low

int low = 0, high = array.length - 1, middle = (low + high) / 2;
// get index of the first k.
while (low <= high) {
    
    
    middle = (low + high) / 2;
    if (k > array[middle]) {
    
    
        low = middle + 1;
    }
    // array[middle] == k 时,令high = middle - 1,继续往前找第一个出现的位置
    else {
    
    
        high = middle - 1;
    }
}
return low;

最后一次出现的位置
当array[middle] == k 时,令low = middle + 1,继续往后找最后一个出现的位置,最后返回high

int low = 0, high = array.length - 1, middle = (low + high) / 2;
// get index of the last k.
while (low <= high) {
    
    
    middle = (low + high) / 2;
    // array[middle] == k 时,令low = middle + 1,继续往后找最后一个出现的位置
    if (k >= array[middle]) {
    
    
        low = middle + 1;
    } else {
    
    
        high = middle - 1;
    }
}
return high;

总代码

public class Solution {
    
    
    public int GetNumberOfK(int[] array, int k) {
    
    
        // 二分查找
        int first = getK(array, k, true);
        int last = getK(array, k, false);
        System.out.println(first + " " + last);
        return last - first + 1;
    }

    public int getK(int[] array, int k, boolean first) {
    
    
        int low = 0, high = array.length - 1, middle = (low + high) / 2;
        if (first) {
    
    
            // get index of the first k.
            while (low <= high) {
    
    
                middle = (low + high) / 2;
                if (k > array[middle]) {
    
    
                    low = middle + 1;
                }
                // array[middle] == k 时,令high = middle - 1,继续往前找第一个出现的位置
                else {
    
    
                    high = middle - 1;
                }
            }
            return low;
        } else {
    
    
            // get index of the last k.
            while (low <= high) {
    
    
                middle = (low + high) / 2;
                // array[middle] == k 时,令low = middle + 1,继续往后找最后一个出现的位置
                if (k >= array[middle]) {
    
    
                    low = middle + 1;
                } else {
    
    
                    high = middle - 1;
                }
            }
            return high;
        }
    }

    public static void main(String[] args) {
    
    
        int[] num = {
    
    1, 2, 3, 3, 3, 3, 4, 5};
        new Solution().GetNumberOfK(num, 6);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43486780/article/details/113797002