欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

在一个非降序排列的数组中,找出数字target出现的次数问题解答

程序员文章站 2022-07-28 20:27:09
题目描述: 在一个非降序排列的数组中,找出数字target出现的次数。 非降序数组,比如{1,1,1,2,3,4,5,5,6} 思路一: 先通过二分查找,找到arr[index...

题目描述:

在一个非降序排列的数组中,找出数字target出现的次数。
非降序数组,比如{1,1,1,2,3,4,5,5,6}

思路一:

先通过二分查找,找到arr[index]等于target的index,在分别向前后遍历,直到arr[index] != target为止。
算法实现简单,但是当数组形如{x,x,...,x},此时查找x的时间复杂度就退化为线性的O(n).

思路二:

1. 首先通过二分查找,找到arr[mid] == target的mid;
2. 然后分别对arr[0~mid]和arr[mid~(arr.length-1)]用二分查找,找到最左边的target的index:left,找到最右边的target的index:right;
3. return right-left+1;

Java代码实现如下:

/**
 * @author Mengjun Li
 * @create 2017/9/29
 * @since 1.0.0
 */
public class Test {
    public static void main(String[] args) {
        int[] arr = new int[]{3, 4, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 10, 11, 12, 13, 14};
        int target = 9;
        System.out.println("输入数组中 "+target+" 的个数为 "+findNum(arr,target));
    }

    public static int findNum(int[] arr, int target) {
        if (arr == null)
            return 0;
        int len = arr.length;
        if (len < 1)
            return 0;
        if (arr[0] > target || target > arr[len - 1])
            return 0;

        int mid = findIndex(arr, 0, len - 1, target);
        if (mid == -1)
            return 0;

        int left = findLeft(arr, 0, mid, target);
        System.out.println("left=" + left);

        int right = findRight(arr, mid, len - 1, target);
        System.out.println("right= " + right);

        return right - left + 1;
    }

    private static int findLeft(int[] arr, int left, int right, int target) {
        while (left < right) {
            int mid = (left + right) >> 1;
            if (arr[mid] == target)
                right = mid;
            else
                left = mid + 1;
        }
        return right;
    }

    private static int findRight(int[] arr, int left, int right, int target) {
        while (left < right) {
            int mid = (left + right + 1) >> 1;
            if (arr[mid] == target)
                left = mid;
            else
                right = mid - 1;
        }
        return left;
    }

    private static int findIndex(int[] arr, int left, int right, int target) {
        int mid;
        while (left <= right) {
            mid = (left + right) >> 1;
            if (arr[mid] == target)
                return mid;
            else if (arr[mid] < target)
                left = mid + 1;
            else
                right = mid - 1;
        }
        return -1;
    }
}

输出如下:

left=6
right= 11
输入数组中 9 的个数为 6