53_剑指offer_java_题目一_排序数组中数字出现次数

目录

 

题目描述

测试用例

题目考点

解题思路

参考解题

排错记录


题目描述

数字在排序数组中出现的次数。

统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。

 

测试用例

  • 功能测试(数组中包含要查找的数字;数组中没有要查找的数字;要查找的数字在数组中出现一次/多次)
  • 边界值测试(查找数组中的最大值、最小值;数组中只有一个数字)
  • 特殊输入测试(表示数组的指针为空指针)

 

题目考点

  • 考察应聘者的只是迁移能力。
  • 考察应聘者对二分查找算法的理解程度。

 

解题思路

一看到在排序(排序数组,一样的数字是挨到一起的)数组中查找,大家一定能想到二分查找法,但是怎么用可以减少复杂度.

 

  1. 利用二分查找法找出最早(左)出现的k的下标

如果中位数为k,看中位数前一个是否为k的话,说明要继续在数组前半段寻找第一个k(递归)不是的话,说明当前中位数为第一个k,返回当前下标;

     2.利用二分查找法找出最晚(右)出现的k的下标

同理,如果中位数为k,看中位数后一个是否为k的话,说明要继续在数组后半段寻找最后一个k(递归)不是的话,说明当前中位数为第一个k,返回当前下标;

 

参考解题

public class Solution {
    // 排序数组中数字出现次数
    // 排序数组,查找,二分查找,确定第一个和最后一个k的位置
    public int GetNumberOfK(int [] array , int k) {
       // 异常
        if(array == null || array.length == 0){
            return 0;
        }
        
        int number =  0;
        int first = GetFirstKIndex(array, k, 0, array.length - 1);
        int last = GetLastKIndex(array, k, 0, array.length - 1);
        
        if(first != -1 && last != -1){
            number = last - first + 1;
        }
        
        return number;
    }
    
    
    // 二分查找改变,找到中位数之后再进行一次比较
    // ------第一个k下标----------------
    public int GetFirstKIndex(int[] array, int k, int start, int end){
        // 异常
            if(start > end || start < 0 || end > array.length - 1){
                return -1;
            }
        
           int midIndex = (start + end)>>1;
           int midData = array[midIndex];
           if(midData == k ){
               if( (midIndex > 0 && array[midIndex - 1] != k )
                  || midIndex == 0){
                   // 中位数为k,中位数前一位不是k,所以中位数为第一个k
                   return midIndex;
               }else{
                   end = midIndex - 1;
               }
           }else if(midData > k){
               end =  midIndex - 1;
           }else{
               start =  midIndex + 1;
           }
           
           return GetFirstKIndex(array, k, start, end);
    }
    
    // ------最后一个k下标--------------------------------
    public int GetLastKIndex(int[] array, int k, int start, int end){
        // 异常
            if(start > end || start < 0 || end > array.length-1){
                return -1;
            }
           int midIndex = (start + end) >> 1;
           int midData = array[midIndex];
           if(midData == k ){
               if((midIndex < array.length - 1 && array[midIndex + 1] != k  ) 
                  || midIndex == array.length - 1){
                   // 中位数为k,中位数后一位不是k,所以中位数为最后一个k
                   return midIndex;
               }else{
                   start = midIndex + 1;
               }
           }else if(array[midIndex] > k){
               end =  midIndex - 1;
           }else{
               start =  midIndex + 1;
           }
           
           return GetLastKIndex(array, k, start, end);
           
    }
}

 

排错记录

if( (midIndex > 0 && array[midIndex - 1] != k )
                  || midIndex == 0)

在书写这一句条件的时候,前后顺序不一样会导致索引溢出错误。先判断midIndex > 0成立之后,再有表达式array[midIndex - 1] 的正确性。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值