正式代码
「力扣」第 374 题讲课正式代码
/**
* 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;
// 在 [1..n] 中查找 pick
while (left <= right) {
int mid = left + (right - left) / 2;
if (guess(mid) == 0) {
return mid;
} else if (guess(mid) == -1) {
// 下一轮搜索区间 [left..mid - 1]
right = mid - 1;
} else {
// guess(mid) == 1
// 下一轮搜索区间 [mid + 1..right]
left = mid + 1;
}
}
return -1;
}
}
复制代码
「力扣」第 704 题讲课正式代码
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len - 1;
// 循环不变量:在 nums[left..right] 查找 target 的下标
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
// 下一轮搜索区间是 [left..mid - 1]
right = mid - 1;
} else {
// nums[mid] < target
// 下一轮搜索区间是 [mid + 1..right]
left = mid + 1;
}
}
return -1;
}
}
复制代码
「力扣」第 35 题讲课正式代码 1
class Solution {
public int searchInsert(int[] nums, int target) {
int len = nums.length;
if (nums[len - 1] < target) {
return len;
}
// 在 nums[left..right] 里查找第一个大于等于 target 的下标
int left = 0;
int right = len - 1;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
// 下一轮搜索区间是 [mid + 1..right]
left = mid + 1;
} else {
// nums[mid] >= target
// 下一轮搜索区间是 [left..mid]
right = mid;
}
}
return left;
}
}
复制代码
「力扣」第 35 题讲课正式代码 2
class Solution {
public int searchInsert(int[] nums, int target) {
int len = nums.length;
// 在 nums[left..right] 里查找第一个大于等于 target 的下标
int left = 0;
int right = len;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
// 下一轮搜索区间是 [mid + 1..right]
left = mid + 1;
} else {
// nums[mid] >= target
// 下一轮搜索区间是 [left..mid]
right = mid;
}
}
return left;
}
}
复制代码
「力扣」第 69 题讲课正式代码
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
int left = 2;
int right = x / 2;
// (x / 2) ^ 2 >= x => x >= 4 或者 x < -4
// 在区间 [left..right] 查找平方以后小于等于 x 的最大整数
while (left < right) {
int mid = (left + right + 1) / 2;
// System.out.println("left = " + left + ", right = " + right);
// System.out.println("mid = " + mid);
if (mid > x / mid) {
// 下一轮搜索区间是 [left..mid - 1]
right = mid - 1;
} else {
// 下一轮搜索区间是 [mid..right]
left = mid;
}
}
return left;
}
}
复制代码
「力扣」第 34 题讲课正式代码
class Solution {
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return new int[] {-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};
}
private int findFirstPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
// 在 nums[left..right] 查找 target 第一次出现的位置
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
// 下一轮搜索区间 [mid + 1..right]
left = mid + 1;
} else {
// 下一轮搜索区间 [left..mid]
right = mid;
}
}
if (nums[left] == target) {
return left;
}
return -1;
}
private int findLastPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
// 在 nums[left..right] 查找 target 最后一次出现的位置
while (left < right) {
int mid = (left + right + 1) / 2;
if (nums[mid] <= target) {
// 下一轮搜索区间 [mid..right]
left = mid;
} else {
// nums[mid] > target
// 下一轮搜索区间 [left..mid - 1]
right = mid - 1;
}
}
return left;
}
}
复制代码
「力扣」第 287 题讲课正式代码
class Solution {
public int findDuplicate(int[] nums) {
int len = nums.length; // len = n + 1, n = len - 1
int left = 1;
int right = len - 1;
// 在 [left..right] 里查找重复的整数
while (left < right) {
int mid = (left + right) / 2;
// nums 中小于等于 mid 的元素的个数
int count = 0;
for (int num: nums) {
if (num <= mid) {
count++;
}
}
if (count > mid) {
// 下一轮搜索区间是 [left..mid]
right = mid;
} else {
// 下一轮搜索区间是 [mid + 1..right]
left = mid + 1;
}
}
return right;
}
}
复制代码
备课代码
「力扣」第 287 题备课代码
class Solution {
public int findDuplicate(int[] nums) {
// n + 1 = nums.length;
int left = 1;
int right = nums.length - 1;
// 例子:有 5 个整数,范围都在 [1..4] 之间,至少有一个数出现了 2 次
while (left < right) {
int mid = (left + right) / 2;
int count = 0;
// 数出 [1..mid] 之间有多少个整数
for (int num: nums) {
if (num <= mid) {
count++;
}
}
if (count > mid) {
// 下一轮搜索区间是 [left..mid]
right = mid;
} else {
// 尝试分析一下:count <= mid 如果小于等于 mid 的整数个数小于等于 mid
left = mid + 1;
}
}
return left;
}
}
复制代码
「力扣」第 69 题备课代码
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
// 计算 (x / 2) ^ 2 > x => x > 4 或者 x < -4
// x = 4
int left = 1;
int right = x / 2;
while (left < right) {
int mid = (left + right + 1) / 2; // left = 1, right = 2, mid = 1
// System.out.println("left => " + left + ", right => " + right);
// System.out.println("mid => " + mid);
if (mid > x / mid) { // 1 > 4 / 2
// 下一轮搜索区间是 [left..mid - 1]
right = mid - 1;
} else {
// 下一轮搜索区间是 [mid..right], [1..2]
left = mid;
}
}
return left;
}
}
复制代码
「力扣」第 374 题备课代码
/**
* 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 = 0;
int right = n;
while (left <= right) {
int mid = left + (right - left) / 2;
if (guess(mid) == 0) {
return mid;
} else if (guess(mid) == -1) {
// 太大了,下一轮在 [left..mid - 1] 里继续猜
right = mid - 1;
} else {
// 太大小,下一轮在 [mid + 1..right] 里继续猜
left = mid + 1;
}
}
return -1;
}
}
复制代码
「力扣」第 34 题备课代码
class Solution {
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return new int[]{-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};
}
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 {
// 此时 nums[mid] > target,应该继续向左边找,即 [left..mid] 区间里找
right = mid;
}
}
if (nums[left] == target) {
return left;
}
return -1;
}
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) {
// 此时 nums[mid] > target,应该继续向左边找,即 [left..mid - 1] 区间里找
right = mid - 1;
} else {
// 即 [mid..right] 区间里找
left = mid;
}
}
return left;
}
}
复制代码