二分查找与实例分析

二分查找

二分查找思路分析
1.首先确定该数组的中间的下标
mid = (left + right)/2
mid = left +(right -left)/2
2.然后让需要查找的数findval和arr[mid]比较
findval > arr[mid] 说明你要查找的数在mid的右边,因此需要递归的向右查找
findval < arr[mid] 说明你要查找的数在mid的左边,因此需要递归的向左查找
findval == arr[mid] 说明你要查找的数找到了,返回
结束递归的条件:
1.找到就结束递归
2.递归整个数组,仍然没有找到findval,也需要结束递归,当left > right 就需要退出
使用二分查找的前提是数组是有序的

public static int binarySearch(int[] arr,int findval){
        if (arr.length == 0)return -1;
        return binarySearch(arr,0,arr.length,findval);
    }

 public static int binarySearch(int[] arr,int left,int right,int findval){
        int mid = (left + right)/2;
        int midval = arr[mid];
        //当 left > right 说明整个数组没有这个值
        if (left > right)return -1;
        if (findval > midval){
            //向右递归
            return binarySearch(arr,mid+1,right,findval);
        }else if (findval < midval){
            //向左递归
            return binarySearch(arr,left,mid-1,findval);
        }else return mid;
    }

当一个有序数组中,有多个相同的数值时,如何将所有的数值都查到

1.在找到mid的时候不要马上返回
2.向mid这个索引值的左边扫描,将所有满足查找值的下标加入到集合中。
3.向mid的这个索引值的右边扫描
4.将集合返回

public static ArrayList<Integer> binarySearchPlus(int[] arr, int left, int right, int findval) {
        int mid = (left + right) / 2;
        int midval = arr[mid];
        //当 left > right 说明整个数组没有这个值
        if (left > right) return null;
        if (findval > midval) {
            //向右递归
            return binarySearchPlus(arr, mid + 1, right, findval);
        } else if (findval < midval) {
            //向左递归
            return binarySearchPlus(arr, left, mid - 1, findval);
        } else {
            ArrayList<Integer> resIndexList = new ArrayList<>();
            //向左边扫描
            int temp = mid - 1;
            while (true) {
                if (temp < 0 || arr[temp] != findval) {
                    break;
                }
                //否则,就temp放入到集合中
                resIndexList.add(temp);
                temp -= 1;//temp左移
            }
            resIndexList.add(mid);

            //向右边扫描
            temp = mid + 1;
            while (true) {
                if (temp > arr.length - 1 || arr[temp] != findval) {
                    break;
                }
                //否则,就temp放入到集合中
                resIndexList.add(temp);
                temp += 1;//temp右移
            }

            return resIndexList;
        }
    }

在刷题的时候学到了三个模板

模板一
int binarySearch(int[] nums, int target){
  if(nums == null || nums.length == 0)
    return -1;

  int left = 0, right = nums.length - 1;
  while(left <= right){
    // Prevent (left + right) overflow
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid - 1; }
  }

  // End Condition: left > right
  return -1;
}

初始条件:left = 0, right = length-1
终止:left > right
向左查找:right = mid-1
向右查找:left = mid+1
LeetCode69题
LeetCode374题
LeetCode33题

模板二
int binarySearch(int[] nums, int target){
  if(nums == null || nums.length == 0)
    return -1;

  int left = 0, right = nums.length;
  while(left < right){
    // Prevent (left + right) overflow
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid; }
  }

  // Post-processing:
  // End Condition: left == right
  if(left != nums.length && nums[left] == target) return left;
  return -1;
}

初始条件:left = 0, right = length
终止:left == right
向左查找:right = mid
向右查找:left = mid+1
LeetCode278题
LeetCode162题
LeetCode153题

模板三
int binarySearch(int[] nums, int target) {
    if (nums == null || nums.length == 0)
        return -1;

    int left = 0, right = nums.length - 1;
    while (left + 1 < right){
        // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid;
        } else {
            right = mid;
        }
    }

    // Post-processing:
    // End Condition: left + 1 == right
    if(nums[left] == target) return left;
    if(nums[right] == target) return right;
    return -1;

初始条件:left = 0, right = length-1
终止:left + 1 == right
向左查找:right = mid

插值查找

插值查找原理介绍
1.插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找
2.将折半查找中的求mid索引的公式,low表示左边索引,high表示右边
key就是findval
3.int midindex = low + (high-low) * (key - arr[low])/(arr[high] - arr[low]);

对于数据量大,关键字分布比较均匀的查找表来说,采用插值查找,速度比较快。
关键字分布不均匀的情况下,该方法不一定比二分查找要好

 public static int insertSearch(int[] arr,int left,int right,int findval){
        //要求数组是有序的 判断是必须的 否则可能会越界
        if (left > right || findval < arr[0] || findval > arr[arr.length-1])return -1;
        int mid = left + (right - left) * (findval - arr[left]) / (arr[right] - arr[left]);
        int midval = arr[mid];
        if (findval > midval){
            //应该向右边递归
            return insertSearch(arr,mid + 1,right,findval);
        }else if (findval < midval){
            return insertSearch(arr,left,mid - 1,findval);
        }else {
            return mid;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值