二分查找
Posted 张乐乐章
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找相关的知识,希望对你有一定的参考价值。
https://labuladong.gitbook.io/algo/mu-lu-ye/er-fen-cha-zhao-xiang-jie
1 int binary_search(int[] nums, int target) { 2 int left = 0, right = nums.length - 1; 3 while(left <= right) { 4 int mid = left + (right - left) / 2; 5 if (nums[mid] < target) { 6 left = mid + 1; 7 } else if (nums[mid] > target) { 8 right = mid - 1; 9 } else if(nums[mid] == target) { 10 // 直接返回 11 return mid; 12 } 13 } 14 // 直接返回 15 return -1; 16 } 17 18 int left_bound(int[] nums, int target) { 19 int left = 0, right = nums.length - 1; 20 while (left <= right) { 21 int mid = left + (right - left) / 2; 22 if (nums[mid] < target) { 23 left = mid + 1; 24 } else if (nums[mid] > target) { 25 right = mid - 1; 26 } else if (nums[mid] == target) { 27 // 别返回,锁定左侧边界 28 right = mid - 1; 29 } 30 } 31 // 最后要检查 left 越界的情况 32 if (left >= nums.length || nums[left] != target) 33 return -1; 34 return left; 35 } 36 37 38 int right_bound(int[] nums, int target) { 39 int left = 0, right = nums.length - 1; 40 while (left <= right) { 41 int mid = left + (right - left) / 2; 42 if (nums[mid] < target) { 43 left = mid + 1; 44 } else if (nums[mid] > target) { 45 right = mid - 1; 46 } else if (nums[mid] == target) { 47 // 别返回,锁定右侧边界 48 left = mid + 1; 49 } 50 } 51 // 最后要检查 right 越界的情况 52 if (right < 0 || nums[right] != target) 53 return -1; 54 return right; 55 }
https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/
35. Search Insert Position(二分查找)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
解法:
1 class Solution { 2 public: 3 int searchInsert(vector<int>& nums, int target) { 4 int low = 0; 5 int high = nums.size() - 1; 6 while(low <= high) { 7 int mid = low + (high - low)/2; 8 if (nums[mid] < target) low = mid + 1; 9 else if (nums[mid] > target) high = mid - 1; 10 else if (nums[mid] == target) return mid; 11 } 12 return low; 13 } 14 };
33. Search in Rotated Sorted Array(二分查找) 旋转数组的二分查找
1 class Solution { 2 public: 3 int search(vector<int>& nums, int target) { 4 int low = 0; 5 int high = nums.size() - 1; 6 while(low <= high) { 7 int mid = low + (high - low)/2; 8 if (nums[mid] == target) return mid; 9 if (nums[low] <= nums[mid]) { // the left is sorted 10 if (nums[low] <= target && target <= nums[mid]) { // target is in the left 11 high = mid - 1; // go to the left to search 12 } else { // target is in hte right 13 low = mid + 1; // go to the right to search 14 } 15 } else { // the right is sorted 16 if (nums[mid] <= target && target <= nums[high]) { // target is in the right 17 low = mid + 1; //go to the right to search 18 } else { // target is in the left 19 high = mid - 1; //go to the left to search 20 } 21 } 22 } 23 return -1; 24 } 25 };
81. Search in Rotated Sorted Array II
旋转数组中有重复的数
给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。
需要判断下相等的情况
1 class Solution { 2 public: 3 int search(vector<int>& nums, int target) { 4 int low = 0; 5 int high = nums.size() - 1; 6 while(low <= high) { 7 int mid = low + (high - low)/2; 8 if (nums[mid] == target) return true; 9 if (nums[low] == nums[mid]) low++; 10 else if (nums[low] < nums[mid]) { // the left is sorted 11 if (nums[low] <= target && target <= nums[mid]) { // target is in the left 12 high = mid - 1; // go to the left to search 13 } else { // target is in hte right 14 low = mid + 1; // go to the right to search 15 } 16 } else { // the right is sorted 17 if (nums[mid] <= target && target <= nums[high]) { // target is in the right 18 low = mid + 1; //go to the right to search 19 } else { // target is in the left 20 high = mid - 1; //go to the left to search 21 } 22 } 23 } 24 return false; 25 } 26 };
153. Find Minimum in Rotated Sorted Array(二分查找)
旋转数组 寻找最小值
解法:寻找
1 class Solution { 2 public: 3 int findMin(vector<int>& nums) { 4 int low = 0; 5 int high = nums.size() - 1; 6 while(low < high) { 7 int mid = low + (high - low ) / 2; 8 if(nums[mid] < nums[high]) { 9 high = mid; 10 } else if(nums[mid] > nums[high]) { 11 low = mid + 1; 12 } else if (nums[mid] == nums[high]) { 13 low = mid + 1 ; 14 } 15 } 16 return nums[low]; 17 } 18 };
154. Find Minimum in Rotated Sorted Array II (旋转重复数组二分查找最小值)
class Solution { public: int findMin(vector<int>& nums) { int low = 0; int high = nums.size() - 1; while(low < high) { int mid = low + (high - low ) / 2; if(nums[mid] < nums[high]) { high = mid; } else if (nums[mid] > nums[high]){ low = mid + 1; } else { // nums[mid] = nums[high] ,并不能确定nums[mid] 究竟在最小值的左侧还是右侧,因此我们不能莽撞地忽略某一部分的元素. high--; } } return nums[low]; } };
162. Find Peak Element(二分查找, 注意二分缩减范围的条件)
1 class Solution { 2 public: 3 int findPeakElement(vector<int>& nums) { 4 int low = 0; 5 int high = nums.size() - 1; 6 while(low < high) { 7 int mid = low + (high - low ) /2; 8 if (nums[mid] < nums[mid+1]) { 9 low = mid + 1; 10 } else { 11 high = mid; 12 } 13 } 14 return low; 15 } 16 };
1 class Solution { 2 public: 3 int guessNumber(int n) { 4 int low = 1; 5 int high = n; 6 while(low < high) { 7 int mid = low + (high - low) /2; 8 if (guess(mid) == 0) return mid; 9 else if(guess(mid) == 1) low = mid + 1; 10 else if(guess(mid) == -1) high = mid; 11 } 12 return low; 13 } 14 };
34. Search for a Range (两次二分查找)
1 class Solution { 2 public: 3 //两次二分 4 vector<int> searchRange(vector<int>& nums, int target) { 5 //首先判断空集 6 if (nums.size()==0){ 7 return {-1,-1}; 8 } 9 //第一次二分,求出第一个>=target的元素 10 int a1=0; 11 int low = 0; 12 int high = nums.size() - 1; 13 while(low<high){ 14 int mid = low +(high-low)/2; 15 if (nums[mid]>=target){ 16 high = mid; 17 }else{ 18 low = mid+1; 19 } 20 } 21 a1 = low; 22 //求出的low可以是0~nums.size() 23 //如果求出的low是num.size()肯定为-1 24 //如果求出的low位置的元素不是target,表明该集合没有target,直接返回[-1,-1] 25 if(low==nums.size()||nums[low]!=target){ 26 return {-1,-1}; 27 } 28 29 //如果left1求出来后,在[0,num.size()-1]的范围内,且num[left1]==target,那么就继续第二次二分求第一个>target的值 30 31 high = nums.size();// 为了处理 【1】1 、【2,2】2 这种情况 32 while(low<high){ 33 int mid = low+(high-low)/2; 34 if (nums[mid]>target){ 35 high = mid; 36 }else{ 37 low = mid+1; 38 } 39 } 40 //经历过第一个二分没返回[-1,-1],表明target肯定在数组里 41 //所以求出的left2可以是1~nums.size(),这时候left2-1肯定是最后一个=target的值的下标 42 return {a1,low-1}; 43 } 44 };
class Solution { public: int mySqrt(int x) { if (x <=1) return x; int low = 0; int high = x ; while(low <= high) { int mid = low + (high-low)/2; if (x/mid > mid) { low = mid + 1; } else if(x/mid < mid) { high = mid - 1; } else { return mid; } } // 正常二分法,如果没找到,返回的是大于target 的位置。此题需要返回小于target的位置。8 的平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。 return low - 1; } };
74. Search a 2D Matrix(两次二分查找,剑指offer 1)
1 class Solution { 2 public: 3 bool searchMatrix(vector<vector<int>>& matrix, int target) { 4 // 先根据最后一列二分查找,确定 target 在哪一行。 5 int n = matrix.size(); //3 6 int m = matrix[0].size();//4 7 int low = 0; 8 int high = n -1 ; 9 while(low < high) { 10 int mid = low + (high - low) / 2; 11 if (matrix[mid][m-1] < target) { 12 low = mid + 1; 13 } else if(matrix[mid][m-1] > target) { 14 high = mid ; 15 } else { 16 return true; 17 } 18 } 19 // low is the target 行 20 int wanted_row = low; 21 low = 0; 22 high = m - 1 ; 23 24 while(low < high) { 25 int mid = low + (high - low) /2; 26 if(matrix[wanted_row][mid] < target) { 27 low = mid + 1; 28 } else if (matrix[wanted_row][mid] > target) { 29 high = mid ; 30 } else { 31 return true; 32 } 33 } 34 return matrix[wanted_row][low] == target; 35 } 36 };
以上是关于二分查找的主要内容,如果未能解决你的问题,请参考以下文章