LC Binary-Search summary

相关思路:有些问题用BS的思路很明显,有些就不是那么清楚,比如有些min-max问题,求满足一定条件的最大值之类的


相关的题目有:

1、Rotated Sorted Array相关问题(idea就是总是有一半的数组是sorted),

2、BS下标控制(偏向左边,右边)与while循环条件(lo<hi还是lo<=hi还是其它)判断控制,以及标准二分返回值的理解(如果没有找到,并且返回值不是0,那返回值就是要插入的位置)

3、一些隐含Binary Search解法的题



贴几个题


33. Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

/*
 * one half is always sorted
 */
public class Solution {
    public int search(int[] nums, int target) {
    	if(nums.length == 0)	return -1;
        int lo = 0, hi = nums.length-1;
        while(lo < hi) {
        	int mid = lo + (hi-lo)/2;
        	if(nums[mid] == target)	return mid;
        	
        	if(nums[mid] < nums[hi]) {
        		if(target > nums[mid] && target <= nums[hi])
        			lo = mid + 1;
        		else
        			hi = mid - 1;
        	} else {
        		if(target >= nums[lo] && target < nums[mid])
        			hi = mid - 1;
        			
        		else
        			lo = mid + 1;
        	}
        }
        
        return nums[lo] == target ? lo : -1;
    }
}

34. Search for a Range

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

/*
 * bias to left & right
 */
public class Solution {
    public int[] searchRange(int[] nums, int target) {
    	if(nums.length == 0)	return new int[]{-1,-1};
        int lo=0, hi=nums.length-1;
        
        while(lo < hi) {
        	int mid = lo + (hi-lo)/2;
        	if(nums[mid] > target) 
        		hi = mid-1;
        	else if(nums[mid] < target)
        		lo = mid+1;
        	else
        		hi = mid;
        }
        int left = lo;
        if(nums[lo] != target)	return new int[]{-1,-1};
        
        lo=0; hi=nums.length-1;
        while(lo < hi) {
        	int mid = lo + (hi-lo+1)/2;
        	if(nums[mid] > target) 
        		hi = mid-1;
        	else if(nums[mid] < target)
        		lo = mid+1;
        	else
        		lo = mid;
        }
        int right = lo;
        
        return new int[]{left, right};
    }
}



162. Find Peak Element

A peak element is an element that is greater than its neighbors.

Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

/*
 * 可以转换为求数组中的最大值
 * 因为只要求出一个合理的peak,所以只要在一个子数组里面求出max也可以
 */
public class Solution {
    public int findPeakElement(int[] nums) {
        int lo = 0, hi = nums.length-1;
        while(lo < hi) {
        	int mid1 = lo + (hi - lo) / 2;
        	int mid2 = mid1 + 1;
        	
        	// num[i] ≠ num[i+1]
        	if(nums[mid2] > nums[mid1]) // 只要找mid2后面的子数组的最大值
        		lo = mid2;
        	else
        		hi = mid1;
        }
        
        return lo;
    }
}


209. Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.


这个题用2 pointer当然是最优的,但是也隐含得可以用二分

因为要求最小值,又要满足一定条件:sum>s,二分范围就是0到数组的长度


74. Search a 2D Matrix && 240. Search a 2D Matrix II

240可以做到O(m+n),最开始想的是在第一行,第一列二分减小后续搜索的范围

/*
 * 1. BS 第一行,第一列narrow down范围
 * 2. Heap:把第一行放到Heap里面,然后不断往下,这个好像是Brute force
 */
public class BS {
    public boolean searchMatrix(int[][] matrix, int target) {
    	if(matrix.length == 0 || matrix[0].length == 0)
    		return false;
    	
        int n = Arrays.binarySearch(matrix[0], target);
        if(n > 0)	return true;
        if(n == -1)	return false;
        
        int[] a = new int[matrix.length];
        for(int i=0; i<a.length; i++)
        	a[i] = matrix[i][0];
        int m = Arrays.binarySearch(a, target);
        if(m >= 0)	return true;
        if(m == -1)	return false;
        
        n = -(n+1);
        m = -(m+1);
        System.out.println(n);
        System.out.println(m);
        for(int i=0; i<m; i++) {
        	if(matrix[i][n-1] > target) {
        		if(Arrays.binarySearch(matrix[i], 0, n, target) > 0)
        			return true;
        	} else if(matrix[i][n-1] == target) {
        		return true;
        	}
        }
        
        return false;
    }
}

后发现更好的解法

/*
 * 有一个O(m+n)的方法
 * 从右上角开始, 比较target 和 matrix[i][j]的值. 如果小于target, 则该行不可能有此数,  所以i++; 
 * 如果大于target, 则该列不可能有此数, 所以j--. 
 * 遇到边界则表明该矩阵不含target
 */
public class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
    	if(matrix.length == 0 || matrix[0].length == 0)
    		return false;
    	
    	int row = 0, col = matrix[0].length-1;
    	while(true) {
    		if(matrix[row][col] == target)
    			return true;
    		else if(matrix[row][col] < target)
    			row ++;
    		else
    			col --;
    		
    		if(row == matrix.length || col == -1)
    			return false;
    	}
    }
}


230. Kth Smallest Element in a BST

LC上把树也放到二分tag里面了,树本身就是一种二分结构嘛

/*
 * 树相关的问题也放到了Binary Search里面
 * 1. 求出左子树的节点数,决策是往左走还是往右走
 * 2. 上面其实可以在求左子树节点数的时候就拿kth求出来了,即inorder tree 遍历
 */
public class Solution {
	int ret = -1;
	int cnt = 0;
    public int kthSmallest(TreeNode root, int k) {
        cnt = k;
        inorder(root);
        return ret;
    }
	private void inorder(TreeNode root) {
		if(root == null)	return;
		inorder(root.left);
		cnt--;
		if(cnt == 0) {
			ret = root.val;
			return;
		}
		inorder(root.right);
	}
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值