二分法简单,从排好序的数组里找数。
时间复杂度就是O(logn)
//二分法查找
#include <iostream>
#define N 100
using namespace std;
inline void Swap(int &a,int &b);
void FastSort(int a[],int left, int right);
bool Find(int a[],int n,int num,int index[],int &count);//n数组个数,num要查找的数,index,返回索引数组,值是0到n-1,count是index的大小
int main()
{
int a[N]={1,2,3,3,5,6,7,8,3,3,3,3,39,10};
int index[N]={0},count=0;
int num;
cin>>num;
FastSort(a,0,N-1);
cout<<Find(a,N,num,index,count)<<endl;
cout<<"count="<<count<<endl;
}
bool Find(int a[],int n,int num,int index[],int &count)
{
int i;
count = 0;
int middle = (n-1)/2;//因为n是数组个数,所以这里的索引都是n-1进行处理
int index_left = 0;
int index_right = n-1;
while(index_left!=index_right)
{
if(a[middle]<num)
{
index_left = middle;
middle = (index_left+index_right)/2;
}
else if(a[middle]>num)
{
index_right = middle;
middle = (index_left+index_right)/2;
}
else
{
index[count] = middle;
count++;
int middle_tmp = middle-1;
while(a[middle_tmp]==num)
{
index[count] = middle_tmp;
count++;
middle_tmp--;
}
middle_tmp = middle+1;
while(a[middle_tmp]==num)
{
index[count] = middle_tmp;
count++;
middle_tmp++;
}
break;
}
}
if(count==0) return false;
else return true;
}
inline void Swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void FastSort(int a[],int left, int right)//aê?êy×é£?left,rightê?êy×éμ??÷òy£??′0oín-1
{
if(left >= right)
return;
int reference = a[right];//°?óò±?μ?×?2???μ??°£?×?oóDè×ó±?ê?′óóú2???£?óò±?ê?D?óú2???
int index_left = left,index_right = right;
int i = 0;
while(index_left!= index_right)
{
while(index_left!=index_right)//á????÷òy??μ?ò??eμ??°
{
if(a[index_left]>reference) break;//?ò?òμ?á?ó|??íùóò·?μ?êy
index_left++;//???òμ??í?ìD?íùóò???÷
}
//cout<<"left="<<index_left<<endl;
while(index_left!=index_right)
{
if(a[index_right]<reference) break;
index_right--;
}
// cout<<"right="<<index_right<<endl;
//?òμ?á?????????2???μ?êy
Swap(a[index_left],a[index_right]);
}
//×?oó×óóò??????μ?ò??eμ?ê±oò£?òò?a?èò??ˉμ?×ó±?????£??ùò?×?oóê?×ó±???????μ?á? óò±?′óóú2???μ?êy×é?ùò?°?2????ú×?oó?a????μ?μ?êy??ò???
Swap(a[index_left],a[right]);
FastSort(a,left,index_left-1);
FastSort(a,index_left+1,right);
}
这个二分法总感觉很啰嗦,参数太多,因为感觉最重要知道存在否即可。
刚看别人的方法感觉很全面,找到这个数的上下界的索引,就完美了
//二分法,返回数的上下界
int FindIndexUp(int a[],int left,int right,int num);//num要查找的数 ,返回上界的索引(最后一个num)
int FindIndexDown(int a[],int left,int right,int num);//num要查找的数 ,返回下界的索引(第一个num)
pair<int,int> FindIndexDownToUp(int a[],int left,int right,int num);
int FindIndexUp(int a[],int left,int right,int num){
int middle=(right-left)/2,index_left=left,index_right=right;
while(index_left<index_right){
middle=(index_right-index_left)/2;
if(a[middle]>num){
index_right = middle;
}
else if(a[middle]<num){
index_left = middle;
}
else{
int index_tmp=middle;
while(a[index_tmp]==num) index_tmp++;
if(index_tmp>right) return right;
else return index_tmp-1;
}
}
return -1;
}
int FindIndexDown(int a[],int left,int right,int num){
int middle=(right-left)/2,index_left=left,index_right=right;
while(index_left<index_right){
middle=(index_right-index_left)/2;
if(a[middle]>num){
index_right = middle;
}
else if(a[middle]<num){
index_left = middle;
}
else{
int index_tmp=middle;
while(a[index_tmp]==num) index_tmp--;
if(index_tmp<left) return left;
else return index_tmp+1;
}
}
return -1;
}
pair<int,int> FindIndexDownToUp(int a[],int left,int right,int num){
int index_up=FindIndexUp(a,left,right,num);
int index_down=FindIndexUp(a,left,right,num);
return make_pair(index_down,index_up);
}
回头看一眼别人的,发现别人这个很简洁啊,可以记下来学习一下这种简洁的做法。,,这个返回的是target上面的数,并且1,2,3,3,3,3,3的情况,认为不存在上界,返回-1。
int BSearchUpperBound(int array[], int low, int high, int target)
{
//Array is empty or target is larger than any every element in array
if(low > high || target >= array[high]) return -1;
int mid = (low + high) / 2;
while (high > low)
{
if (array[mid] > target)
high = mid;
else
low = mid + 1;
mid = (low + high) / 2;
}
return mid;
}
int BSearchLowerBound(int array[], int low, int high, int target)
{
//Array is empty or target is less than any every element in array
if(high < low || target <= array[low]) return -1;
int mid = (low + high + 1) / 2; //make mid lean to large side
while (low < high)
{
if (array[mid] < target)
low = mid;
else
high = mid - 1;
mid = (low + high + 1) / 2;
}
return mid;
}
pair<int, int> SearchRange(int A[], int n, int target)
{
pair<int, int> r(-1, -1);
if (n <= 0) return r;
int lower = BSearchLowerBound(A, 0, n-1, target);
lower = lower + 1; //move to next element
if(A[lower] == target)
r.first = lower;
else //target is not in the array
return r;
int upper = BSearchUpperBound(A, 0, n-1, target);
upper = upper < 0? (n-1):(upper - 1); //move to previous element
//since in previous search we had check whether the target is
//in the array or not, we do not need to check it here again
r.second = upper;
return r;
}
最大子数组的问题:
,在一个数组里面找和最大的子数组。
分解开来,从middle开始,最大子数组存在midd左边,右边,这两种情况可以递归分解问题,第三种情况是最大子数组会跨过middle,这样的话,最大子数组就是i到middle到j的数组,这样对左右i到middl和j到middle的情况可以遍历找一下这样解决。
//最大子数组问题
#include <iostream>
#define N 16
using namespace std;
typedef pair<pair<int,int>,int> sub; //定义一个存子数组的数据类型,前一个pair是子数组的左右索引,后一个是子数组的和
sub FindMaxSub(int a[],int left,int right);//left,right是左右索引
sub FindMaxCrossSub(int a[],int left,int middle,int right);//这种事最大子数组跨过middle的情况
int main()
{
//sub a;
//a = make_pair(make_pair(0,3),6);
//cout<<a.first.first<<endl;
//int a[4]={13,-3,20,-3};
int n=N;
int a[N]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-55,-22,15,-4,7};
sub max_sub = FindMaxSub(a,0,n-1);
cout<<"left="<<max_sub.first.first<<endl;
cout<<"right="<<max_sub.first.second<<endl;
cout<<"sum="<<max_sub.second<<endl;
return 0;
}
sub FindMaxSub(int a[],int left,int right)//这里a用数组头指针,left,right就不是从0开始的索引了
{
if(left==right) return make_pair(make_pair(left,right),a[left]);
int i;
int middle = (left+right)/2;
sub left_sub = FindMaxSub(a,left,middle);
cout<<"left sum="<<left_sub.second<<endl;
sub right_sub = FindMaxSub(a,middle+1,right);
cout<<"right sum="<<right_sub.second<<endl;
sub cross_sub = FindMaxCrossSub(a,left,middle,right);
cout<<"cross sum="<<cross_sub.second<<endl;
if(left_sub.second>right_sub.second && left_sub.second>cross_sub.second) return left_sub;
else if(right_sub.second>left_sub.second && right_sub.second>cross_sub.second) return right_sub;
else return cross_sub;
}
sub FindMaxCrossSub(int a[],int left,int middle,int right)
{
int sum_tmp=0;
int sum_left=0,sum_right=0;
int index_left = middle;
int index_right = middle+1;
int i;
for(i=middle;i>=left;i--)
{
sum_tmp += a[i];
if(sum_left<sum_tmp)
{
index_left = i;
sum_left = sum_tmp;
}
}
sum_tmp = 0;
for(i=middle+1;i<=right;i++)
{
sum_tmp +=a[i];
if(sum_right<sum_tmp)
{
index_right = i;
sum_right = sum_tmp;
}
}
return make_pair(make_pair(index_left,index_right),sum_left+sum_right);
}