文章摘要:文章收集各个网站包括力扣,洛谷二分查找习题。同时给出我的Python、C++代码,但是代码不作过多解释。
超链。PS1:这是最最简单的二分查找了。就是调用了一个api注意一下。PS2:还有一点需要注意就是:对于C++尽量去使用 r + ( r − l ) / 2 r+(r-l)/2 r+(r−l)/2而不是 ( r + l ) / 2 (r+l)/2 (r+l)/2,虽然两者在数学上是等效的但是后者可能造成数值溢出(显而易见;事实上这道题C++使用后一种就过不了)。数值溢出应该是有解决方法,但是我不知道所以后种公式。
Python
# The isBadVersion API is already defined for you.
# def isBadVersion(version: int) -> bool:
class Solution:
def firstBadVersion(self, n: int) -> int:
if isBadVersion(1)==1:
return 1
l,r=1,n
while l+1!=r:
m=(l+r)//2
if isBadVersion(m)==0:
l=m
else:
r=m
return r
C++
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
if(isBadVersion(1)==1){return 1;}
int l=1,r=n;
while(l+1!=r){
int m=l+(r-l)/2;
if(isBadVersion(m)==0){l=m;}
else{r=m;}
}
return r;
}
};
超链。PS:也很简单。注意一下返回即可。
Python
class Solution:
def searchInsert(self,nums:List[int],target:int)->int:
if target<nums[0]:
return 0
if target>nums[-1]:
return len(nums)
l,r=0,len(nums)
while l<=r:
m=(l+r)//2
if target<nums[m]:
r=m-1
elif target>nums[m]:
l=m+1
else:
return m
return r+1
C++
class Solution{
public:
int searchInsert(vector<int>&nums,int target){
//C++中不能使用负数进行索引
int n=nums.size();
int l=0,r=n-1;
if(target<nums[0]){return 0;}
if(target>nums[n-1]){return n;}
while(l<=r){
int m=(l+r)/2;
if(target>nums[m]){l=m+1;}
else if(target<nums[m]){r=m-1;}
else{return m;}
}
return r+1;
}
};
超链。PS:也很简单。纵着来一次,横着来一次。
Python
class Solution:
def searchMatrix(self,matrix:List[List[int]],target:int)->bool:
if target<matrix[0][0]:
return False
if target>matrix[-1][-1]:
return False
lt=[]
for i in matrix:
for j in i:
lt.append(j)
l,r=0,len(lt)-1
while l<=r:
m=(l+r)//2
if target>lt[m]:
l=m+1
elif target<lt[m]:
r=m-1
else:
return True
return False
C++
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int n=matrix.size(),m=matrix[0].size();
if(target<matrix[0][0]){return 0;}
if(target>matrix[n-1][m-1]){return 0;}
int l1=0,r1=n-1;
while(l1<=r1){
int m1=(l1+r1)/2;
if(target>matrix[m1][0]){l1=m1+1;}
else if(target<matrix[m1][0]){r1=m1-1;}
else{return 1;}
}
int l2=0,r2=m-1;
while(l2<=r2){
int m2=(l2+r2)/2;
if(target>matrix[r1][m2]){l2=m2+1;}
else if(target<matrix[r1][m2]){r2=m2-1;}
else{return 1;}
}
return 0;
}
};
超链。也很简单。每行都给它来一次。
Python
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
if target<matrix[0][0]:
return 0
if target>matrix[-1][-1]:
return 0
for i in matrix:
l,r=0,len(i)-1
while l<=r:
m=(l+r)//2
if target>i[m]:
l=m+1
elif target<i[m]:
r=m-1
else:
return 1
return 0
C++
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int n=matrix.size(),m=matrix[0].size();
if(target<matrix[0][0]){return 0;}
if(target>matrix[n-1][m-1]){return 0;}
for(int i=0;i<n;i++){
int l=0,r=m-1;
while(l<=r){
int m=(r+l)/2;
if(target>matrix[i][m]){l=m+1;}
else if(target<matrix[i][m]){r=m-1;}
else{return 1;};
}
}
return 0;
}
};
超链。PS:这里我们始终保证 n u m s [ l ] > n u m s [ l − 1 ] , n u m s [ r ] > n u m s [ r + 1 ] nums[l]>nums[l-1],nums[r]>nums[r+1] nums[l]>nums[l−1],nums[r]>nums[r+1]。当 r = l r=l r=l时有 n u m s [ l − 1 ] < n u m s [ l ] = n u m s [ r ] < n u m s [ r + 1 ] nums[l-1]
Python
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l,r=0,len(nums)-1
while l!=r:
m1=(l+r)//2;m2=(l+r)//2+1
if nums[m1]<nums[m2]:
l=m2
else:
r=m1
return r
C++
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int l=0,r=nums.size()-1;
while(l!=r){
int m1=(l+r)/2,m2=(l+r)/2+1;
if(nums[m1]<nums[m2]){l=m2;}
if(nums[m1]>nums[m2]){r=m1;}
}
return l;
}
};
超链。PS1:也很简单。先把旋转的点找到,然后再来找目标值,两次二分法就好了。PS2:注意一下特殊条件以及边界情况即可。
Python
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums)==1:
if nums[0]==target:
return 0
return -1
if nums[0]<nums[-1]:
l,r=0,len(nums)-1
else:
l_new,r_new=0,len(nums)-1
while l_new+1!=r_new:
m_new=(l_new+r_new)//2
if nums[m_new]>nums[l_new]:
l_new=m_new
if nums[m_new]<nums[r_new]:
r_new=m_new
if target>=nums[0]:
l,r=0,l_new
else:
l,r=r_new,len(nums)-1
if target<nums[l] or target>nums[r]:
return -1
while l<=r:
m=(l+r)//2
if nums[m]>target:
r=m-1
elif nums[m]<target:
l=m+1
else:
return m
return -1
C++
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.size()==1){
if(nums[0]==target){return 0;}
return -1;
}
int r,l;
if(nums[0]<nums[nums.size()-1]){
l=0,r=nums.size()-1;
}
else{
int l_new=0,r_new=nums.size()-1;
while(l_new+1!=r_new){
int m_new=l_new+(r_new-l_new)/2;
if(nums[m_new]>nums[l_new]){l_new=m_new;}
if(nums[m_new]<nums[r_new]){r_new=m_new;}
}
if(target>=nums[0]){l=0,r=l_new;}
else{l=r_new,r=nums.size()-1;}
}
if(target<nums[l]||target>nums[r]){return -1;}
while(l<=r){
int m=l+(r-l)/2;
if(nums[m]>target){r=m-1;}
else if(nums[m]<target){l=m+1;}
else{return m;}
}
return -1;
}
};
超链:。PS:思路同上,略有改动。
Python
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums)==1:
if nums[0]==target:
return True
return False
l,r=0,len(nums)-1
while True:
cnt=0
if nums[l]==nums[l+1] and l+1!=r:
l+=1;cnt+=1
if nums[r]==nums[r-1] and r-1!=l:
r-=1;cnt+=1
if cnt==0:
break
if l+1==r:
if nums[l]==target or nums[r]==target:
return True
else:
return False
else:
if nums[l+1]>nums[r] or nums[r-1]<nums[l]:
a,b=l,r
while l+1!=r:
m=l+(r-l)//2
if nums[m]>=nums[l]:
l=m
if nums[m]<=nums[r]:
r=m
if target>=nums[a]:
l,r=a,l
else:
l,r=r,b
if target<nums[l] or target>nums[r]:
return False
while l<=r:
m=l+(r-l)//2
if nums[m]>target:
r=m-1
elif nums[m]<target:
l=m+1
else:
return True
return False
C++
class Solution {
public:
bool search(vector<int>& nums, int target) {
if(nums.size()==1){
if(nums[0]==target){return true;}
else{return false;}
}
int l=0,r=nums.size()-1;
while(1){
int cnt=0;
if(nums[l]==nums[l+1]&&l+1!=r){l+=1;cnt+=1;}
if(nums[r]==nums[r-1]&&r-1!=l){r-=1;cnt+=1;}
if(cnt==0){break;}
}
if(l+1==r){
if(nums[l]==target||nums[r]==target){return true;}
else{return false;}
}
else{
if(nums[l+1]>=nums[r]||nums[r-1]<=nums[l]){
int a=l,b=r;
while(l+1!=r){
int m=l+(r-l)/2;
if(nums[m]>=nums[l]){l=m;}
if(nums[m]<=nums[r]){r=m;}
}
if(target>=nums[a]){r=l;l=a;}
else{l=r;r=b;}
}
}
if(target<nums[l]||target>nums[r]){return false;}
while(l<=r){
int m=l+(r-l)/2;
if(nums[m]>target){r=m-1;}
else if(nums[m]<target){l=m+1;}
else{return true;}
}
return false;
}
};
超链。PS:会上面两道题,这道题就简单。这道题只包含上面的第一步。
Python
class Solution:
def findMin(self, nums: List[int]) -> int:
if len(nums)==1:
return nums[0]
if nums[0]<nums[-1]:
return nums[0]
l,r=0,len(nums)-1
while l+1!=r:
m=l+(r-l)//2
if nums[m]>nums[l]:
l=m
if nums[m]<nums[r]:
r=m
return nums[r]
C++
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size()==1){return nums[0];}
if(nums[0]<nums[nums.size()-1]){return nums[0];}
int l=0,r=nums.size()-1;
while(l+1!=r){
int m=l+(r-l)/2;
if(nums[m]>nums[l]){l=m;}
if(nums[m]<nums[r]){r=m;}
}
return nums[r];
}
};
超链。PS:思路同上,略有改动。
Python
class Solution:
def findMin(self, nums: List[int]) -> int:
if len(nums)==1:
return nums[0]
l,r=0,len(nums)-1
while True:
cnt=0
if nums[l]==nums[l+1] and l+1!=r:
l+=1;cnt+=1
if nums[r]==nums[r-1] and r-1!=l:
r-=1;cnt+=1
if cnt==0:
break
if l+1==r:
return min(nums[l],nums[r])
else:
if nums[l+1]>nums[r] or nums[r-1]<nums[l]:
while l+1!=r:
m=l+(r-l)//2
if nums[m]>=nums[l]:
l=m
if nums[m]<=nums[r]:
r=m
return nums[r]
else:
return nums[0]
C++
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size()==1){return nums[0];}
int l=0,r=nums.size()-1;
while(1){
int cnt=0;
if(nums[l]==nums[l+1]&&l+1!=r){l+=1;cnt+=1;}
if(nums[r]==nums[r-1]&&r-1!=l){r-=1;cnt+=1;}
if(cnt==0){break;}
}
if(l+1==r){
if(nums[l]<nums[r]){return nums[l];}
else{return nums[r];}
}
else{
if(nums[l+1]>nums[r]||nums[r-1]<nums[l]){
while(l+1!=r){
int m=l+(r-l)/2;
if(nums[m]>=nums[l]){l=m;}
if(nums[m]<=nums[r]){r=m;}
}
return nums[r];
}
else{return nums[0];}
}
}
};
PS:鉴于博主没有系统学习过C++只有一点点C基础所以输入输出我是完全不懂所以洛谷就只给Python代码了吧。之后也不打算进行补充毕竟语言只是一种工具。
超链。PS:最简单的思路便是对于每个查询进行二分查找。但是还是感觉有点浪费时间,所以我们这样来做。首先对于查询列表进行排序以及删除重复元素。每次查询,左界选择上一次的索引右边一个就好。
Python
def function1(l,r,x,lt):
while l<=r:
m=l+(r-l)//2
if lt[m]>x:
r=m-1
elif lt[m]<x:
l=m+1
else:
return m
return -1
def function2(x,lt):
while True:
if x>=1 and lt[x]==lt[x-1]:
x-=1
else:
return x
n,m=map(int,input().strip().split())
lt1=[int(i) for i in input().strip().split()]
lt2=[int(i) for i in input().strip().split()]
lt3=list(set(lt2));lt3.sort();zd={};l=0
for i in lt3:
x=function1(l,n-1,i,lt1)
if x!=-1:
l=x+1
if x==-1:
zd[i]=-1
else:
zd[i]=function2(x,lt1)+1
for i in lt2:
print(zd[i],end=" ")
感觉到这基本练得差不多了。数值分析也有很多二分查找思想案例,数值分析我也想好好搞;洛谷官方题单也有二分查找经典题单,洛谷官方题单希望做完。这篇文章就到这了,其他二分查找案例见以后的更新博文。希望下次能够熟练掌握C++吧。