算法学习之二分法

**定义:**二分法是一种在有序数组中查找某一特定元素的算法
算法最坏的时间复杂度为O(logn)
注意:1.数据类型是有范围的,采用L+(R-L)/2更合适
2.注意start=mid+1和end=mid-1,防止死循环
3.数据量不可过大

        STL的lower_bound()和upper_bound()
        返回小于等于查找元素的下标和返回大于等于查找元素的下标

代码示例:

using namespace std;
#include<iostream>

int binary_search(int a[],int key){
	int start=0;
	int end=sizeof(a)-1;
	while(start<=end){
		int mid=start+(end-start)/2;
		if(a[mid]<key){
			start=mid+1;
		}
		if(a[mid]>key){
			end=mid-1;
		}
		if(a[mid]==key){
			return mid;
		}
	}
	return -1;
}

int main(){
	int a[]={1,3,4,5,7,8};
	cout<<binary_search(a,4);

}

例1.二分查找lower_bound
有n(1<=n<=1000005)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请找出序列中第1个大于x的数的下标!
Input
输入数据包含多个测试实例,每组数据由两行组成,第一行是n和x,第二行是已经有序的n个整数的数列。
Output
对于每个测试实例,请找出序列中第1个小于x的数的位置。
Sample Input
3 3
1 2 4
Sample Output
2

using namespace std;
#include<iostream>
int binary_search(int a[], int key) {
	int start = 0;
	int end = sizeof(a) ;
	while (start < end) {
		int mid = start + (end - start) / 2;
		
	
		if (a[mid] >= key) {
			end = mid ;
			}
			else {
			start = mid + 1;
			}

		}
	
	return start;
}
int main() {
	int m;
	int n;
	int p;
	cin >> m >> n;
	int a[50] = {0};
	for (int i = 0; i < m; i++) {
		cin >> p;
		a[i] = p;
	}
	cout << binary_search(a, n);
}

例2:输入n ( n≤100,000)个整数,找出其中的两个数,它们之和等于整数m(假定肯定有解)。题中所有整数都能用int 表示。

方法一:暴力搜

        复杂度为O(n*n)
int main() {
	int m;
	int n;
	cin >> n >> m;
	for (int i = 0; i <= n; i++) {
		for (int k = i + 1; k <= n; k++) {
			if (i + k == m) {
				cout << i << " " << k << endl;
			}
		}
	}

}

方法二:二分法

     复杂度为O(nlogn)
void bin_search(int a[],int n,int p) {
	
	
     for (int i = 0; i < p; i++) {
		for (int start = i,end=p-1; start <=end;) {
			int mid = start + (end - start) / 2;

			if (a[mid] > n - a[i]) {
				end = mid - 1;
			}
			if (a[mid] < n - a[i]) {
				start = mid + 1;
			}
			if (a[mid] == n - a[i]&&a[mid]!=a[i]) {
				cout << a[i] << " " << a[mid] << endl;
				break;
			}
		}
		
		
	}
}
int main() {
	int p;
	int n;
	cin >> p >> n;//输入p(数的个数),n(总和)
	int a[1000];
	for (int i = 0; i < p; i++) {
		a[i] = i + 1;
	}
	bin_search(a, n, p);
}

方法三:双指针法

     复杂度为O(n)
void bin_search(int m[],int n,int b) {
	int start = 0;
	int end = b-1;
	while (start < end) {

		if (m[start] + m[end] < n) {
			start++;
		}
		if (m[start] + m[end] > n) {
			end--;
		}
		if (m[start] + m[end] == n && m[start] != m[end]) {
			cout << m[start] << " " << m[end] << endl;
			start++;
		}
	}
}
int main() {
	int p;
	int n;
	cin >> p >> n;//输入p(数的个数),n(总和)
	int a[1000];
	for (int i = 0; i < p; i++) {
		a[i] = i + 1;
	}
	bin_search(a, n,p);

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值