二分查找框架
int binarySearch(int[] nums, int target) {int left = 0, right = ...;while(...) {int mid = (right + left) / 2;if (nums[mid] == target) {...} else if (nums[mid] < target) {left = ...} else if (nums[mid] > target) {right = ...}}return ...;}
分析二分查找的一个技巧是:不要出现 else,而是把所有情况用 else if 写清楚,这样可以清楚地展现所有细节。
基本的二分搜索
int binarySearch(int[] nums, int target) {int left = 0;int right = nums.length - 1; // 注意while(left <= right) { // 注意int mid = (right + left) / 2;if(nums[mid] == target)return mid;else if (nums[mid] < target)left = mid + 1; // 注意else if (nums[mid] > target)right = mid - 1; // 注意}return -1;}
逻辑分析
因为我们初始化 right = nums.length - 1所以决定了我们的「搜索区间」是 [left, right]所以决定了 while (left <= right)同时也决定了 left = mid+1 和 right = mid-1因为我们只需找到一个 target 的索引即可所以当 nums[mid] == target 时可以立即返回
寻找左侧边界的二分搜索
int left_bound(int[] nums, int target) {if (nums.length == 0) return -1;int left = 0;int right = nums.length; // 注意while (left < right) { // 注意int mid = (left + right) / 2;if (nums[mid] == target) {right = mid;} else if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid; // 注意}}return left;}
逻辑分析
因为我们初始化 right = nums.length所以决定了我们的「搜索区间」是 [left, right)所以决定了 while (left < right)同时也决定了 left = mid + 1 和 right = mid因为我们需找到 target 的最左侧索引所以当 nums[mid] == target 时不要立即返回而要收紧右侧边界以锁定左侧边界
寻找右侧边界的二分查找
int right_bound(int[] nums, int target) {if (nums.length == 0) return -1;int left = 0, right = nums.length;while (left < right) {int mid = (left + right) / 2;if (nums[mid] == target) {left = mid + 1; // 注意} else if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid;}}return left - 1; // 注意}
逻辑分析
因为我们初始化 right = nums.length所以决定了我们的「搜索区间」是 [left, right)所以决定了 while (left < right)同时也决定了 left = mid + 1 和 right = mid因为我们需找到 target 的最右侧索引所以当 nums[mid] == target 时不要立即返回而要收紧左侧边界以锁定右侧边界又因为收紧左侧边界时必须 left = mid + 1所以最后无论返回 left 还是 right,必须减一
