# (18/39) Binary Search 38道题

### 1# Leetcode 367. Valid Perfect Square

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:
Input: 16
Returns: True

Example 2:
Input: 14
Returns: False

mid = 128 => 128 * 128 > 256 => end = mid = 128;
mid = 64 => 64 * 64 > 256 => end = mid = 64;
mid = 32 => 32 * 32 > 256 => end = mid = 32;
mid = 16 => 16 * 16 = 256 => return true;

mid = 8 => 8 * 8 > 15 => end = mid = 8;
mid = 4 => 4 * 4 > 15 => end = mid = 4;
mid = 2 => 2 * 2 < 15 => start = mid = 2; end = 4;
mid = 3 => 3 * 3 < 15 => start = mid = 3; end = 4;
start + 1 = 3 + 1 = 4 = end, while loop end;
start = 3, 3 * 3 != 15 and end = 4, 4 * 4 != 15;
so return false;

``````public class Solution {
public boolean isPerfectSquare(int num) {
if (num < 1) {
return false;
}
long start = 1;
long end = num;
while (start + 1 < end) {
long mid = start + (end - start) / 2;
if (mid * mid == num) {
return true;
} else if (mid * mid < num) {
start = mid;
} else {
end = mid;
}
}
if (start * start == num || end * end == num) {
return true;
}
return false;
}
}
``````

### 3# Leetcode 167 Two Sum II - Input array is sorted

``````/**
*  Method one: Two points 一刷
*    时间复杂度为O(n), 空间复杂度为O(1)。
*/
public int[] twoSum(int[] numbers, int target) {
int start = 0;
int end = numbers.length - 1;
while (start < end) {
if (numbers[start] + numbers[end] < target) {
start ++;
}
else if(numbers[start] + numbers[end] > target) {
end --;
}
else {
break;
}
}
return new int[]{start + 1, end + 1};
}

/**
*     Method 2: Binary Search 一刷
*     时间复杂度为O(logn), 空间复杂度为O(1)。
*/
public class Solution {
public int[] twoSum(int[] numbers, int target) {
int[] result = {0,0};
int index1 = 0;
int index2 = 0;

for(int i = 0; i < numbers.length - 1; i++ ){
index1 = i + 1;
if(numbers[i] > target) {
return result;
}

int gap = target - numbers[i];
int start = i + 1;
int end = numbers.length - 1;

while(start + 1 < end){
int mid = start + (end - start) / 2;
if(numbers[mid] == gap) {
index2 = mid + 1;
result[0] = index1;
result[1] = index2;
return result;
}
if (numbers[mid] > gap) {
end = mid;
}
if (numbers[mid] < gap) {
start = mid;
}
}
if (numbers[start] == gap) {
result[0] = index1;
result[1] = start + 1;
}
if (numbers[end] == gap) {
result[0] = index1;
result[1] = end + 1;
}
}
return result;
}
}
``````

### 4# Leetcode 441. Arranging Coins

You have a total of n coins that you want to form in a staircase shape, where every k-th row must have exactly k coins.

Given n, find the total number of full staircase rows that can be formed.

n is a non-negative integer and fits within the range of a 32-bit signed integer.

Example 1: n = 5
The coins can form the following rows:
¤
¤ ¤
¤ ¤
Because the 3rd row is incomplete, we return 2.

Example 2: n = 8
The coins can form the following rows:
¤
¤ ¤
¤ ¤ ¤
¤ ¤
Because the 4th row is incomplete, we return 3.

1 + 2 + 3 + ... + k <= n
=>
(k * ( k + 1)) / 2 <= n

``````public class Solution {
public int arrangeCoins(int n) {
int start = 0;
int end = n;
int mid = 0;
while (start <= end){
mid = start + (end - start) / 2 ;
if ((0.5 * mid * mid + 0.5 * mid ) <= n){
start = mid + 1;
}else{
end = mid - 1;
}
}
return start - 1;
}
}
``````

### 5# Leetcode 35. Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

``````public class Solution {
public int searchInsert(int[] nums, int target) {
if (nums.length == 0 || nums == null) {
return 0;
}
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
}
else if (nums[mid] < target) {
start = mid;
}
else {
end = mid;
}
}
if (nums[start] >= target) {
return start;
}
else if (nums[end] >= target) {
return end;
}
else {
return end + 1;
}
}
}
``````

### 6# Leetcode 374. Guess Number Higher or Lower

We are playing the Guess Game. The game is as follows:

I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I'll tell you whether the number is higher or lower.

You call a pre-defined API guess(int num) which returns 3 possible results (-1, 1, or 0):

-1 : My number is lower
1 : My number is higher
0 : Congrats! You got it!

Example:
n = 10, I pick 6.
Return 6.

``````/* The guess API is defined in the parent class GuessGame.
@return -1 if my number is lower, 1 if my number is higher, otherwise return 0
int guess(int num); */

public class Solution extends GuessGame {
public int guessNumber(int n) {
int start = 1, end = n;
while(start + 1 < end) {
int mid = start + (end - start) / 2;
if(guess(mid) == 0) {
return mid;
} else if(guess(mid) == 1) {
start = mid;
} else {
end = mid;
}
}
if(guess(start) == 1) {
return end;
}
return start;
}
}
``````

### 7# Leetcode 69. Sqrt(x)

Implement int sqrt(int x).
Compute and return the square root of x.

``````public class Solution {
public int mySqrt(int x) {
long start = 1;
long end = x;
while (start + 1 < end) {
long mid = start + (end - start) / 2;
if(mid * mid <= x) {
start = mid;
}
else {
end = mid;
}
}
if(end * end <= x) {
return (int)end;
}
return (int)start;
}
}

``````

### 8# Leetcode 278. First Bad Version

You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.

Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad.

You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.

``````/* The isBadVersion API is defined in the parent class VersionControl.

public class Solution extends VersionControl {
int start = 1;
int end = n;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
end = mid;
}
else {
start = mid;
}
}
return start;
}
return end;
}
}
``````

### 9# Leetcode 475. Heaters

Winter is coming! Your first job during the contest is to design a standard heater with fixed warm radius to warm all the houses.

Now, you are given positions of houses and heaters on a horizontal line, find out the minimum radius of heaters so that all houses could be covered by those heaters.

So, your input will be the positions of houses and heaters separately, and your expected output will be the minimum radius standard of heaters.

Note:
Numbers of houses and heaters you are given are non-negative and will not exceed 25000.

Positions of houses and heaters you are given are non-negative and will not exceed 10^9.

As long as a house is in the heaters' warm radius range, it can be warmed.

Example 1:
Input: [1,2,3],[2]
Output: 1
Explanation: The only heater was placed in the position 2, and if we use the radius 1 standard, then all the houses can be warmed.

Example 2:
Input: [1,2,3,4],[1,4]
Output: 1
Explanation: The two heater was placed in the position 1 and 4. We need to use radius 1 standard, then all the houses can be warmed.

``````public class Solution {
public int findRadius(int[] houses, int[] heaters) {
//sort
Arrays.sort(houses);
Arrays.sort(heaters);

for( int house: houses) {
int local = binarySearch(heaters, house);
}
}

private int binarySearch(int[] heaters, int target) {
int start = 0;
int end = heaters.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (heaters[mid] == target) {
return 0;
} else if (heaters[mid] < target) {
start = mid;
} else {
end = mid;
}
}
return Math.min (Math.abs(target - heaters[start]),
Math.abs(target - heaters[end]));
}
}
``````

### 10# Leetcode 349. Intersection of Two Arrays

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2].

Note:
Each element in the result must be unique.
The result can be in any order.

``````public class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1 == null || nums2 == null) {
return null;
}

HashSet<Integer> set = new HashSet<>();
Arrays.sort(nums1);

for (int i = 0; i < nums2.length; i++) {
if(set.contains(nums2[i])){
continue;
}
if(binarySearch(num1, nums2[i])) {
}
}

int[] result = new int[set.size()];
int index = 0;
for (Integer num : set) {
result[index++] = num;
}
return result;
}

private boolean binarySearch(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return false;
}
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return true;
}
else if (nums[mid] < target) {
start = mid;
}
else {
end = mid;
}
}

if(nums[start] == target || nums[end] == target) {
return true;
}
return false;
}
}
``````

### 11# Leetcode 350. Intersection of Two Arrays II

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2].

Note:
Each element in the result should appear as many times as it shows in both arrays.
The result can be in any order.
What if the given array is already sorted? How would you optimize your algorithm?
What if nums1's size is small compared to nums2's size? Which algorithm is better?
What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?

``````public class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int index1 = 0;
int index2 = 0;
List<Integer> list = new ArrayList<>();
while(index1 < nums1.length && index2 < nums2.length) {
if (nums1[index1] == nums2[index2]) {
index1++;
index2++;
} else if (nums1[index1] < nums2[index2]) {
index1++;
} else if (nums1[index1] > nums2[index2]) {
index2++;
}
}
int[] result = new int[list.size()];
int index = 0;
for (int element: list) {
result[index++] = element;
}
return result;
}
}
``````

### 12# Leetcode 153. Find Minimum 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).

Find the minimum element.

You may assume no duplicate exists in the array.

``````public class Solution {
public int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int target = nums[nums.length - 1];

while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] <= target) {
end = mid;
}
else {
start = mid;
}
}
if (nums[start] <= target) {
return nums[start];
} else {
return nums[end];
}
}
}
``````

### 13# Leetcode 154. Find Minimum in Rotated Sorted Array II

``````// version 1: just for loop is enough
public class Solution {
public int findMin(int[] nums) {
//  这道题目在面试中不会让写完整的程序
//  只需要知道最坏情况下 [1,1,1....,1] 里有一个0
//  这种情况使得时间复杂度必须是 O(n)
//  因此写一个for循环就好了。
//  如果你觉得，不是每个情况都是最坏情况，你想用二分法解决不是最坏情况的情况，那你就写一个二分吧。
//  反正面试考的不是你在这个题上会不会用二分法。这个题的考点是你想不想得到最坏情况。
int min = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] < min)
min = nums[i];
}
return min;
}
}

// version 2: use *fake* binary-search
public class Solution {
/**
* @param num: a rotated sorted array
* @return: the minimum number in the array
*/
public int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}

int start = 0, end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == nums[end]) {
// if mid equals to end, that means it's fine to remove end
// the smallest element won't be removed
end--;
} else if (nums[mid] < nums[end]) {
end = mid;
} else {
start = mid;
}
}

if (nums[start] <= nums[end]) {
return nums[start];
}
return nums[end];
}
}
``````

### 14# Leetcode 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.

``````public class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[start] < nums[mid]) {
if (nums[start] <= target && target <= nums[mid]) {
end = mid;
} else {
start = mid;
}
}
else {
if (nums[mid] <= target && target <= nums[end]) {
start = mid;
}
else {
end = mid;
}
}
}
if (nums[start] == target) {
return start;
}
if (nums[end] ==  target) {
return end;
}
return -1;
}
}
``````

### 15# Leetcode 81. Search in Rotated Sorted Array II

Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?
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).

Write a function to determine if a given target is in the array.

The array may contain duplicates.

``````public class Solution {
// 这个问题在面试中不会让实现完整程序
// 只需要举出能够最坏情况的数据是 [1,1,1,1... 1] 里有一个0即可。
// 在这种情况下是无法使用二分法的，复杂度是O(n)
// 因此写个for循环最坏也是O(n)，那就写个for循环就好了
//  如果你觉得，不是每个情况都是最坏情况，你想用二分法解决不是最坏情况的情况，那你就写一个二分吧。
//  反正面试考的不是你在这个题上会不会用二分法。这个题的考点是你想不想得到最坏情况。
public boolean search(int[] nums, int target) {
for (int i = 0; i < nums.length; i ++) {
if (nums[i] == target) {
return true;
}
}
return false;
}
}
``````

### 16# Leetcode 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].

``````public class Solution {
public int[] searchRange(int[] nums, int target) {
if (nums.length == 0) {
return new int[]{-1,-1};
}
int[] bound = new int[2];
// search for left bound
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
end = mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[start] == target) {
bound[0] = start;
} else if (nums[end] == target) {
bound[0] = end;
} else {
bound[0] = bound[1] = -1;
return bound;
}
//search for right bound
start = 0;
end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
start = mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[end] == target) {
bound[1] = end;
} else if (nums[start] == target) {
bound[1] = start;
} else {
bound[0] = bound[1] = -1;
return bound;
}
return bound;
}
}
``````

### 17# Leetcode 74. Search a 2D Matrix

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

Integers in each row are sorted from left to right.
The first integer of each row is greater than the last integer of the previous row.

For example,
Consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
Given target = 3, return true.

``````public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
return false;
}
int row = matrix.length;
int column = matrix[0].length;
int start = 0;
int end = row * column - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
int number = matrix[mid / column][mid % column];
if (number == target) {
return true;
} else if (number < target) {
start = mid;
} else {
end = mid;
}
}
if (matrix[start / column][start % column] == target) {
return true;
} else if (matrix[end / column][end % column] == target) {
return true;
}
return false;
}
}
``````

### 18# Leetcode 240. Search a 2D Matrix II

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
For example,

Consider the following matrix:

[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]

Given target = 5, return true.
Given target = 20, return false.

``````public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
int row = 0;
int col = matrix[0].length - 1;
while (col >= 0 && row <= matrix.length - 1) {
if (target == matrix[row][col]) {
return true;
} else if (target < matrix[row][col]) {
col--;
} else if (target > matrix[row][col]) {
row ++;
}
}
return false;
}
}
``````

### 22# Leetcode 454. 4Sum II

Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero.

To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.

Example:
Input:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]

Output:
2

Explanation:
The two tuples are:

1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

### 23# Leetcode 436. Find Right Interval

Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i.

For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array.

Note:
You may assume the interval's end point is always bigger than its start point.
You may assume none of these intervals have the same start point.
Example 1:
Input: [ [1,2] ]
Output: [-1]
Explanation: There is only one interval in the collection, so it outputs -1.

Example 2:
Input: [ [3,4], [2,3], [1,2] ]
Output: [-1, 0, 1]
Explanation: There is no satisfied "right" interval for [3,4].
For [2,3], the interval [3,4] has minimum-"right" start point;
For [1,2], the interval [2,3] has minimum-"right" start point.

Example 3:
Input: [ [1,4], [2,3], [3,4] ]
Output: [-1, 2, -1]
Explanation: There is no satisfied "right" interval for [1,4] and [3,4].
For [2,3], the interval [3,4] has minimum-"right" start point.

### 24# Leetcode 300. Longest Increasing Subsequence

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?

### 32# Leetcode 4. Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3], nums2 = [2]
The median is 2.0

Example 2:
nums1 = [1, 2], nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5

### 35# Leetcode 410. Split Array Largest Sum

Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays.

Note:
If n is the length of array, assume the following constraints are satisfied:

1 ≤ n ≤ 1000

1 ≤ m ≤ min(50, n)
Examples:

Input:
nums = [7,2,5,10,8]
m = 2
Output:
18

Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.

### 37# Leetcode 174. Dungeon Game

The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.

The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.

Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).

In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.

Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.

For example, given the dungeon below, the initial health of the knight must be at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN.

| -2(K) | -3 | 3 |
|---|---|---|
| -5 | -10 | 1 |
| 10 | 30 | -5(P) |

Notes:

The knight's health has no upper bound.
Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.

### 39# LintCode: Last Position of Target

Find the last position of a target number in a sorted array. Return -1 if target does not exist.
Example
Given [1, 2, 2, 4, 5, 5].
For target = 2, return 2.
For target = 5, return 5.
For target = 6, return -1.

``````public int lastPosition(int[] nums, int target) {
if (nums.length == 0 || nums == null) {
return -1;
}
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid]==target) {
start = mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[end] == target) {
return end;
}
if (nums[start] == target) {
return start;
}
return -1;
}
``````

### 40# LintCode: Maximum Number in Mountain Sequence

Given a mountain sequence of n integers which increase firstly and then decrease, find the mountain top.

Example
Given nums = [1, 2, 4, 8, 6, 3] return 8
Given nums = [10, 9, 8, 7], return 10

``````public int mountainSequence(int[] nums) {
if (nums.length == 0 || nums == null) {
return -1;
}
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] > nums[mid + 1]) {
end = mid;
} else {
start = mid;
}
}
return Math.max(nums[start], nums[end]);
}
``````