相关思路:有些问题用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};
}
}
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);
}
}