1.查找局部最小的数
class Solution {
public:
int getLessIndex(vector<int> arr) {
int n=arr.size();
if(n==0) return -1;
else if(n==1) return 0;
else if(arr[0]<arr[1]) return 0;
else if(arr[n-1]<arr[n-2]) return n-1;
else return getindex(arr,1,n-2);
}
int getindex(vector<int> &arr,int left,int right)
{
while(left<=right)
{
int mid=left+(right-left)/2; //防止溢出,比使用(left+right)/2更好
if(arr[mid]<arr[mid-1]&&arr[mid]<arr[mid+1]) return mid;
else if(arr[mid-1]<arr[mid]) right=mid-1;
else if(arr[mid+1]<arr[mid]) left=mid+1;
}
return -1;
}
};
2.查找在最左边出现的数
class LeftMostAppearance {
public:
int findPos(vector<int> arr, int n, int num) {
int res=-1;
if(n==0) return res;
int left=0,right=n-1;
while(left<=right)
{
int mid=left+(right-left)/2;
if(arr[mid]==num)
{
right=mid-1;
res=mid;
}
else if(arr[mid]>num) right=mid-1;
else left=mid+1;
}
return res;
}
};
3.查找循环有序数组最小值
找出递增数组通过循环移动后的最小值
class MinValue {
public:
int getMin(vector<int> arr, int n) {
int left = 0;
int right = n-1;
int middle = 0;
int i = 0;
int res = 0;
while(left <= right)
{
middle = left+(right-left)/2;
if(arr[left] < arr[right])
{
return arr[left];
}
if(arr[left] == arr[right])
{
for(i=left;i<right;i++)
{
if(arr[i] < arr[left])
{
break;
}
}
return arr[i];
}
if(arr[middle] < arr[right])
{
right = middle;
}
else
{
left = middle+1;
}
}
return arr[left];
}
};
4.查找最左原数
如果arr[i]=i,则arr[i]称为原数。
class Find {
public:
int findPos(vector<int> arr, int n) {
if(n==0||arr[0]>n-1||arr[n-1]<0) return -1;
int res=-1;
int left=0,right=n-1,mid;
while(left<=right)
{
mid=left+(right-left)/2;
if(arr[mid]==mid)
{
res=mid;
right=mid-1;
}
else if(arr[mid]>mid)
{
right=mid-1;
}
else
{
left=mid+1;
}
}
return res;
}
};
5.统计完全二叉树结点个数
class CountNodes {
public:
int count(TreeNode* root) {
int nn=0;
if(root==NULL) return 0;
if(root->left==NULL) return 1;
if(root->right==NULL) return 2;
TreeNode* left=root->left,*right=root->right;
int ln=1,rn=1;
while(left)
{
++ln;
left=left->left;
}
while(right)
{
++rn;
right=right->right;
}
if(rn==ln)
{
nn+=pow(2,ln-1);//如果左右子树高度相等,则左子树是满二叉树
nn+=count(root->right);
}
else
{
nn+=pow(2,rn-1);
nn+=count(root->left);//如果左右子树高度不相等,则右子树是满二叉树
}
return nn;
}
};
6.快速N次方
class QuickPower {
public:
int getPower(int k, int N) {
if(N==0)
return 1;
long res=1;
long tmp=k;
while(N)
{
int bit=N&1;
N>>=1;
if(bit==1) res*=tmp;
tmp=(tmp*tmp)%1000000007;
res%=1000000007;
}
return (int)res;
}
};
5,6看起来和二分搜索关系不大,但是其实都是运用的二分搜索的思想,即不断的"扔掉一半的数据,考虑另一半的数据"。
7.有序矩阵查找
1,2,3
4,5,6
7,8,9
class Finder {
public:
bool findX(vector<vector<int> > mat, int n, int m, int x) {
if(m<=0||n<=0)
return false;
int i=0,j=m-1;//从矩阵的右上角的点往左或往下考虑
while(i<n&&j>=0)
{
if(mat[i][j]>x) --j;
else if(mat[i][j]<x) ++i;
else return true;
}
return false;
}
};
8.查找第一个值等于给定值的元素
9.查找最后一个值等于给定值的元素
10.查找第一个大于等于给定值的元素
11.查找最后一个小于等于给定值的元素
8到11为二分查找的变种,只需要在判断条件里面稍微修改一下即可。