二分查找(simple难度)
https://leetcode-cn.com/problems/binary-search/
class Solution {
public int binarySearch(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len - 1;//注意,左闭右闭区间,所以right = len - 1
// 目标元素可能在 左闭右闭 区间:[left, right],但下面while循环是 < 而不是 <= ,要注意
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
// 下一轮搜索区间是 [mid + 1, right],索引mid对应元素一定不符合要求,所以左边界是mid+1
left = mid + 1;
} else {
// 下一轮搜索区间是 [left, mid],索引mid对应元素可能不符合要求,所以右边界是mid
right = mid;
}
}
if (nums[left] == target) {
return left;
}
return -1;
}
}
或者:
class Solution {
public int binarySearch(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len - 1;
// 定义target在 左闭右闭 的区间里,[left, right]
//若if (nums[mid] == target) 在while内判断,则是left <= right
//若不在while内判断相等时的情况,则是left < right
while (left <= right) {// 当left==right,区间[left, right]依然有效
int mid = left + (right - left) / 2; //防止溢出,等同于(left + right)/2
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
//因为target要在左闭右闭的区间里,因为nums[mid]不满足条件,
//所以要把mid从区间里剔除,所以搜索区间变为[mid + 1, right]
left = mid + 1; // target在右区间,所以[mid + 1, right]
} else {
right = mid - 1; // target在左区间,所以[left, mid - 1]
}
}
return -1;
}
}
第一个错误的版本(simple难度)
https://leetcode-cn.com/problems/first-bad-version/
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
while (left < right){
int mid = left + (right - left) / 2;
if(isBadVersion(mid) == false){
left = mid + 1;
}else{
right = mid;
}
}
return left;
}
}
猜数字大小(simple难度)
https://leetcode-cn.com/problems/guess-number-higher-or-lower/
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* int guess(int num);
*/
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left = 1;
int right = n;
while (left <= right) {
int mid = left + (right - left) / 2;
if(guess(mid) == 0){
return mid;
}else if(guess(mid) == -1){
right = mid - 1;
}else{
left = mid + 1;
}
}
return left;
}
}
排列硬币(simple难度)
https://leetcode-cn.com/problems/arranging-coins/
排列硬币可以转化成寻找 <=n
的最大等差数列和的尾项。
细节看代码注释。
class Solution {
public int arrangeCoins(int n) {
long left = 0;
long right = n;
while (left < right) {
long mid = left + (right - left + 1) / 2;
//硬币排列类似等差数列求和
//等差数列求和公式:(首项 + 尾项) * 项数 / 2
//本题中首项为1,尾项为mid,项数也为mid
//本题要满足:(首项 + 尾项) * 项数 / 2 <= n
//整理可得:mid * (mid + 1) <= 2 * n
if (mid * (mid + 1) > (long) 2 * n) {
right = mid - 1;
} else {
left = mid;
}
}
return (int) left;
}
}
搜索插入位置(simple难度)
https://leetcode-cn.com/problems/search-insert-position/
class Solution {
public int searchInsert(int[] nums, int target) {
int n = nums.length;
int left = 0;
int right = n - 1; // 定义target在左闭右闭的区间里,[left, right]
while (left <= right) { // 当left==right,区间[left, right]依然有效
int mid = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[mid] > target) {
right = mid - 1; // target 在左区间,所以[left, mid - 1]
} else if (nums[mid] < target) {
left = mid + 1; // target 在右区间,所以[mid + 1, right]
} else { // nums[mid] == target
return mid;
}
}
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, -1]
// 目标值等于数组中某一个元素 return mid;
// 目标值插入数组中的位置 [left, right],return right + 1
// 目标值在数组所有元素之后的情况 [left, right], return right + 1
return right + 1;
}
}
或:
public class Solution {
public int searchInsert(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return 0;
}
// 特判
if (nums[len - 1] < target) {
return len;
}
int left = 0;
int right = len - 1;
while (left < right) {
int mid = left + (right - left) / 2;
// 严格小于 target 的元素一定不是解
if (nums[mid] < target) {
// 下一轮搜索区间是 [mid + 1, right]
left = mid + 1;
} else {
// 下一轮搜索区间是 [left, mid]
right = mid;
}
}
return left;
}
}
在排序数组中查找元素的第一个和最后一个位置(medium)
https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/si-lu-hen-jian-dan-xi-jie-fei-mo-gui-de-er-fen-cha/
来源:力扣(LeetCode)
class Solution {
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return new int[]{-1, -1};
}
//firstPosition == -1 说明数组中没有target,则返回[-1,-1]
int firstPosition = findFirstPosition(nums, target);
if (firstPosition == -1) {
return new int[]{-1, -1};
}
int lastPosition = findLastPosition(nums, target);
return new int[]{firstPosition, lastPosition};
}
//查找相同target值的左边界
private int findFirstPosition(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) {
// 下一轮搜索区间是 [mid + 1, right]
left = mid + 1;
} else if (nums[mid] == target) {
// 下一轮搜索区间是 [left, mid],一直向左搜寻,找到左边界
right = mid;
} else {
// nums[mid] > target,下一轮搜索区间是 [left, mid - 1]
right = mid - 1;
}
}
if (nums[left] == target) {
return left;
}
return -1;
}
//查找相同target值的右边界
private int findLastPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left + 1) / 2;
if (nums[mid] > target) {
// 下一轮搜索区间是 [left, mid - 1]
right = mid - 1;
} else if (nums[mid] == target){
// 下一轮搜索区间是 [mid, right],一直向右搜寻,找到右边界
left = mid;