在排序数组中查找数字(Java实现)

题目:统计一个数字在排序数组中出现的次数。注意,这里指的是升序数组。例如:

2,4,6,6,7,25

如果查找目标是 6,那么就应该返回2,因为6出现了2次

如果查找目标是9,那么就返回0,表示没有出现。

因为数组是有序的,而且是升序,那么很容易就想到了二分查找法来解决,但是,正常的二分查找,只是找到了中间的一个,无法确定有多少个,因此有必要对其进行改进。思路:

(1)找到目标第一次出现的下标,这里用start表示吧

(2)找到目标最后一次出现的下标,这里用end表示吧

(3)结果就是 (end - start + 1)个
 

具体实现,解释都在代码中了:

package com.test;

public class Solution {
    public int search(int[] nums, int target) {
        int left = getFirstKIndex(nums,target);
        if (left==-1){
            return 0;
        }
        int right = getLastKIndex(null,target,left);
        return right - left + 1;
    }


    public int getFirstKIndex(int[] a,int k){
        //如果数组为空,则直接返回
        if (a == null || a.length==0){
            return -1;
        }
        int start = 0;
        int end = a.length - 1;
        int mid = 0;
        while (start <= end){
            mid = (start + end) / 2;
            if (a[mid] == k){
                //判断是否是第一个k,这里有两种情况:
                //(1)该元素是数组的第一个元素,那它肯定是第一个k了
                //(2)由于数组是升序的,如果它的前一个元素不等于k,那么它也是第一个k了
                if ((mid > 0 && a[mid -1]!=k) || mid == 0 ){
                    return mid;
                }else {
                    //左边还有等于k的元素,所以继续往左边找
                    end = mid - 1;
                }

            }else if (a[mid] > k){
                //中间值大于k,如果k存在,那么也是存在于左边,往左边找
                end = mid -1;
            }else {
                //中间值小于k,如果k存在,那么也是存在于右边,往右边找
                start = mid + 1;
            }
        }
        //循环没有找到,肯定没有找到k
        return -1;
    }

    public int getLastKIndex(int[] a,int k,int firstKIndex){
        //如果数组为空,则直接返回
        if (a == null || a.length==0){
            return -1;
        }
        int start = firstKIndex;
        int end = a.length - 1;
        //最后一个就是k,直接返回就行了
        if (start == end){
            return start;
        }
        int mid = 0;
        int len = a.length - 1;
        while (start <= end){
            mid = (start + end) / 2;
            if (a[mid] == k){
                //判断是否是最后一个k,这里有两种情况:
                //(1)该元素是数组的最后一个元素,那它肯定是最后一个k了
                //(2)由于数组是升序的,如果它的后一个元素不等于k,那么它也是最后一个k了
                if ((mid < len && a[mid+1]!=k) || mid == len ){
                    return mid;
                }else {
                    //右边还有等于k的元素,往右边找
                    start = mid + 1;
                }

            }else if (a[mid] > k){
                //中间值大于k,如果k存在,那么也是存在于左边,往左边找
                end = mid -1;
            }else {
                //中间值小于k,如果k存在,那么也是存在于右边,往右边找
                start = mid + 1;
            }
        }
        //循环没有找到,肯定没有找到k
        return -1;
    }

}

测试是通过的:

在排序数组中查找数字(Java实现)_第1张图片

你可能感兴趣的:(算法)