查找算法(极客时间记录)

一.二分查找法--(极客时间记录)

二分查找法能解决的问题,更倾向于用散列表或者二叉树。二分法更适用于近似的查找问题。

容易出错的细节:

  • 终止条件;
  • 区间上下界更新的方法;
  • 返回值的选择;
import java.util.Scanner;
import java.util.Arrays;

public class BinaraySearch {

	public static int rank(int key,int[] a) {
		int lo=0;
		int hi=a.length-1;
		while(lo<=hi) {
			int mid=lo+(hi-lo)/2;
			if(key<a[mid]) hi=mid-1;
			else if(key>a[mid]) lo=mid+1;
			else return mid;
		}
		return -1;
	}
	
	public static int bssearch(int key,int[] a) {
		return bsearchInternally(key, a, 0, a.length-1);
	}
	private static int bsearchInternally(int key, int[] a, int low, int high) {
		// TODO Auto-generated method stub
		int mid = low + ((high - low)>>1);
		if(a[mid] == key) return mid;
		else if(a[mid] > key) {
			return bsearchInternally(key, a, low, mid -1);
		}else if(a[mid] < key) {
			return bsearchInternally(key, a, mid+1, high);
		}
		return 0;
	}
	//变式1---如果排序的数组中有重复出现的数字,找出第一个相等的数字
	public static int bsearchQuestion1(int value, int[] a) {
		int low = 0;
		int high = a.length - 1;
		while(low <= high) {
			int mid = low + ((high - low)>>1);
			if(a[mid] < value) {
				low = mid +1;
			}else if(a[mid] > value) {
				high = mid - 1;
			}else {//发生修改的地方
				if((mid == 0) || (a[mid - 1] != value)) return mid;//若果mid到了0,那前面肯定没有数字了,如果前面和value相等,则修改high
				else high = mid - 1;
			}
		}
		return -1;
	}
	//变式2---如果排序的数组中有重复出现的数字,找出最后一个相等的数字
	public static int bsearchQuestion2(int value, int[] a) {
		int low = 0;
		int high = a.length - 1;
		while(low <= high) {
			int mid = low + ((high - low)>>1);
			if(a[mid] < value) {
				low = mid +1;
			}else if(a[mid] > value) {
				high = mid - 1;
			}else {//发生修改的地方
				if((mid == a.length - 1) || (a[mid + 1] != value)) return mid;//若果mid到了0,那前面肯定没有数字了,如果前面和value相等,则修改high
				else low = mid + 1;
			}
		}
		return -1;
	}
	//变式3---找出第一个大于等于给定值的数字
	public static int bsearchQuestion3(int value, int[] a) {
		int low = 0;
		int high = a.length - 1;
		while(low <= high) {
			int mid = low + ((high - low)>>1);
			if(a[mid] < value) {
				low = mid + 1;
			}else {
				if((mid == 0) || (a[mid - 1] < value))return mid;
				else high = mid -1;
			}
		}
		return -1;
	}
	
	//变式4---找出最后一个小于等于给定值的数字
	public static int bsearchQuestion4(int value, int[] a) {
		int low = 0;
		int high = a.length - 1;
		while(low <= high) {
			int mid = low + ((high - low)>>1);
			if(a[mid] < value) {
				low = mid + 1;
			}else {
				if((mid == a.length - 1) || (a[mid + 1] > value))return mid;
				else low = mid + 1;
			}
		}
		return -1;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//标准输入,读取分割后转换成int
		System.out.println("输入数组:");
		Scanner sc = new Scanner(System.in);
		String str = sc.nextLine().toString();
		String arr[] = str.split(" ");
		int[] a = new int[arr.length];
		for(int j=0;j<=a.length-1;j++) {
			a[j] = Integer.parseInt(arr[j]);
			//System.out.print(a[j] + " ");
		}
		Arrays.sort(a);
		
		System.out.println("输入要查询的数");
		Scanner x=new Scanner(System.in);
		int number = x.nextInt();
		System.out.println(bsearchQuestion3(number,a));
	}

}

思考题:当给定的数组是循环有序的数组,如何实现二分查找算法;

题目对应Leetcode33.

猜你喜欢

转载自blog.csdn.net/runkui8905/article/details/89040613