二分查找及其引申

二分查找

基本的二分查找

leetcode二分查找
注意while循环里面的判断以及边界的取值:
在 int high = arr.length-1; 时候,相当于两端都闭区间 [left, right]
high =mid-1;
while(low <= high)

	public static int binary(int [] arr,int num) {
		int low =0;
		int high = arr.length-1;
		while(low<=high) {
			int mid  =low +(high-low)/2;
			if(arr[mid]>num) {
				high =mid-1;
			}else if(arr[mid]<num) {
				low =mid+1;
			}else if(arr[mid]==num) {
				return mid;
			}	
		}
		return -1;
	}

如果

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

在 int high = arr.length; 时候,相当于左闭右开区间 [left, right)
high =mid;
while(low < high)

左边

leetcode搜索插入位置

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

如果不存在返回 -1.

	public static int left_bound_fuyi(int [] arr,int num) {
		//not find, return -1
		int low =0;
		int high = arr.length-1;
		while(low<=high) {
			int mid  =low +(high-low)/2;
			if(arr[mid]>num) {
				high =mid-1;
			}else if(arr[mid]<num) {
				low =mid+1;
			}else if(arr[mid]==num) {
				high = mid-1;
			}
		}
		if(low == arr.length) 
			return -1;
		return arr[low]==num?low:-1;
	}

右边

如果元素有重复,返回右边的元素,即小于等于它的最大的元素

	public static int right_bound1(int [] arr,int num) {
		//high = arr.length;
		int low =0;
		int high = arr.length;
		while(low<high) {
			int mid  =low +(high-low)/2;
			if(arr[mid]>num) {
				high =mid;
			}else if(arr[mid]<num) {
				low =mid+1;
			}else if(arr[mid]==num) {
				low =mid+1;
			}
		}
		return low-1;
	}
	public static int right_bound(int [] arr,int num) {
		//high = arr.length - 1;
		int low =0;
		int high = arr.length - 1;
		while(low <= high) {
			int mid  =low +(high-low)/2;
			if(arr[mid]>num) {
				high = mid - 1;
			}else if(arr[mid]<num) {
				low = mid+1;
			}else if(arr[mid]==num) {
				low = mid+1;
			}
		}
		return high;//return low - 1;
	}

返回 -1

	
	public static int right_bound_fuyi(int [] arr,int num) {
		//arr 娑擃厼鐨禍锟� num 閻ㄥ嫬鍘撶槐鐘虫箒  娑擄拷
		int low =0;
		int high = arr.length;
		while(low<high) {
			int mid  =low +(high-low)/2;
			if(arr[mid]>num) {
				high =mid;
			}else if(arr[mid]<num) {
				low =mid+1;
			}else if(arr[mid]==num) {
				low =mid+1;
			}
			
		}
		if(low==0) return -1;
		return arr[low-1]==num?(low-1):-1;
	}

最接近元素的k个值

找到最接近的k个值
1.双指针
在这里插入图片描述
在这里插入图片描述

	public List<Integer> findClosestElement_zhizhen(int[] arr,int k, int x){
		int i =0;
		int j =arr.length-1;
		int len = arr.length;
		while(len>k) {
			if(Math.abs(arr[i]-x)>Math.abs(arr[j]-x))
				i++;
			else
				j--;
			len--;
		}
		List<Integer> res = new ArrayList<>();
		for(int index= i;index<=j;index++) {
			res.add(arr[index]);
		}
		return res;
	}
	public List<Integer> findClosestElement_binary(int[] arr,int k, int x){
		/*
		 * binarysearch閿涳拷 閹垫儳鍩岀捄婵堫瀲閺堬拷鏉╂垵灏梻瀵告畱鐠ч鍋�
		 * [mid,mid+k]閸氭啀闂堢姵瀚�
		 */
		int i =0;
		int j =arr.length-k;
		while(i<j) {
			int mid = i+(j-i)/2;
			if(Math.abs(arr[mid]-x)>Math.abs(arr[mid+k]-x))//
				i=mid+1;
			else
				j=mid;
		}
		List<Integer> res = new ArrayList<>();
		for(int index= i;index<i+k;index++) {
			res.add(arr[index]);
		}
		return res;
	}	

2.二分查找
在这里插入图片描述

	public List<Integer> findClosestElements(int[] arr, int k, int x) {
		int i =0;
		int j =arr.length - k - 1;
		while(i <= j) {
			int mid = i+(j-i)/2;
			if(Math.abs(arr[mid]-x)>Math.abs(arr[mid+k]-x))
				i=mid+1;
			else
				j=mid - 1;
		}
		List<Integer> res = new ArrayList<>();
		for(int index= i;index<i+k;index++) {
			res.add(arr[index]);
		}
		return res;
}

有序的二维矩阵

判断是否有某个数

/* 思路

  • 矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
  • 因此从左下角开始查找,当要查找数字比左下角数字大时。右移
  • 要查找数字比左下角数字小时,上移
    */
    public boolean Find(int target,int [][] array) {
        int row=0;
        int col=array[0].length-1;
        while(row<=array.length-1&&col>=0){
            if(target==array[row][col])
                return true;
            else if(target>array[row][col])
                row++;
            else
                col--;
        }
        return false;
 
    }

第k个数

两层控制:left=right,同时count = k时候输出所求的值
查找小于等于mid的时候,从最后一行的第一列依次查找,同上一个题的思路

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
    	int left = matrix[0][0];
    	int n = matrix.length;
    	int right = matrix[n - 1][n - 1];
    	while(left < right) {
    		int mid = (left + right)/2;
    		int count = findCount(matrix, mid);
    		if(count < k) 
    			left = mid + 1;
    		else
    			right = mid;
    	}
    	return left;
    }
    public int findCount(int[][] matrix, int mid) {
    	int n = matrix.length;
    	int i = n - 1;
    	int j = 0;
    	int count = 0;
    	//每一列小于等于mid的个数
    	while(i >= 0 && j < n){
    		if(matrix[i][j] <= mid) {
    			count += i + 1;
    			j ++;
    		}else {
    			i --;
    		}
    	}
    	return count;    	
    }
}

两个有序数组

合并两个有序数组

有序数组的第k个数

有序数组的中位数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值