二分查找及插值查找算法

百度百科

https://baike.baidu.com/item/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/10628618?fr=aladdin

思路

代码:

package com.search;


public class BinarySearch {
	
	public static void main(String[] args) {
		int[] arr = {1,2,3,4,5,6};
		int binarySearch = binarySearch(arr, 0, arr.length-1, 7);
		System.out.println(binarySearch);
		
	}
	
	public static int binarySearch(int [] arr,int left,int right,int findNum){
		// 如果找不到返回-1,否则会死递归
		if (left > right) {
			return -1;
		}
		int mid = (left + right) / 2;
		int midValue = arr[mid];
		if (findNum > midValue) { //向右递归
			return binarySearch(arr, mid + 1, right, findNum);
		} else if (findNum <midValue) {
			return binarySearch(arr, left, mid - 1, findNum);
		} else {
			return mid;
		}
	}
}

 

测试:

上面的代码只能找一个索引,倘若有多个值呢?比如{1,2,3,4,5,6,6,6};

优化后代码如下:

package com.search;

import java.util.ArrayList;
import java.util.List;

public class BinarySearch {
	
	public static void main(String[] args) {
		int[] arr = {1,2,3,3,3,4,5,6,6,6};
		 List<Integer> binarySearch2 = binarySearch2(arr, 0, arr.length-1, 6);
		System.out.println(binarySearch2);
		
	}
	
	public static int binarySearch(int [] arr,int left,int right,int findNum){
		// 如果找不到返回-1,否则会死递归
		if (left > right) {
			return -1;
		}
		int mid = (left + right) / 2;
		int midValue = arr[mid];
		if (findNum > midValue) { //向右递归
			return binarySearch(arr, mid + 1, right, findNum);
		} else if (findNum <midValue) {
			return binarySearch(arr, left, mid - 1, findNum);
		} else {
			
			return mid;
		}
	}
	
	public static List<Integer> binarySearch2(int [] arr,int left,int right,int findNum){
		// 如果找不到返回-1,否则会死递归
		if (left > right) {
			return new ArrayList<>();
		}
		int mid = (left + right) / 2;
		int midValue = arr[mid];
		if (findNum > midValue) { //向右递归
			return binarySearch2(arr, mid + 1, right, findNum);
		} else if (findNum <midValue) {
			return binarySearch2(arr, left, mid - 1, findNum);
		} else { // 主要这里的修改,找到索引号好不要直接返回
			//不要返回,继续分别从两边继续找
			List<Integer> res = new ArrayList<>();
			// 不要忘了第一次找到的索引
			res.add(mid);
			//从左边找
			int temp = mid - 1;
			while (true) {
				if(temp < 0 || arr[temp] != findNum) {
					break;
				}
				res.add(temp);
				temp--;
				
			}
			// 右边找
			temp = mid + 1;
			while (true) {
				if(temp> arr.length-1 || arr[temp] != findNum) {
					break;
				}
				res.add(temp);
				temp++;
				
			}
			
			return res;
		}
	}
}

测试结果:

 插值查找算法

代码:

 

package com.search;

import java.util.ArrayList;
import java.util.List;

public class InsertValueSearch {
	
	public static void main(String[] args) {
		int[] arr = {1,2,3,4,5,6,7,8,9,10};
		int insertValueSearch = InsertValueSearch.insertValueSearch(arr, 0, arr.length - 1, 1);
		System.out.println(insertValueSearch);
		
	}
	
	public static int insertValueSearch(int [] arr,int left,int right,int findNum){
		System.out.println("查找次数");
		// 如果找不到返回-1,否则会死递归
		if (left > right
			|| findNum < arr[0] || findNum > arr[arr.length - 1]) { // 这两个必须加上,否则mid可能因为findNum太大或者太小而越界!!!
			return -1;
		}
		// 主要改这里,自适应
		int mid = left + (right - left)*(findNum-arr[left])/(arr[right]-arr[left]);
		int midValue = arr[mid];
		if (findNum > midValue) { //向右递归
			return insertValueSearch(arr, mid + 1, right, findNum);
		} else if (findNum <midValue) {
			return insertValueSearch(arr, left, mid - 1, findNum);
		} else {
			
			return mid;
		}
	}
	
	
}

对比结果:

int[] arr = {1,2,3,4,5,6,7,8,9,10};

如果用插值查找算法找1和10,一次便可找到,二分查找就要三次。

插值查找注意事项

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值