二分查找
int BinarySearch(int a[], int size, int p) {
int L = 0; // 查找区间的左端点
int R = size - 1; // 查找区间的右端点
// int lastPos = -1; // 到目前为止找到的最优解
while (L <= R) { // 如果查找区间不为空就继续查找
int mid = L+(R-L)/2; // 取查找区间正中元素的下标
if (p == a[mid])
return mid;
else if (p > a[mid])
L = mid + 1; // 设置新的查找区间的左端点
else {
// lastPos = mid;
R = mid - 1; // 设置新的查找区间的右端点
}
}
// return lastPos;
return -1;
} // 复杂度O(nlog(n))
二分法求方程的根
题目描述
求下面方程的一个根:f(x) = x^3 - 5x^2 + 10x - 80 = 0
若求出的根是a,则要求 |f(a)| <= 10^-6
解题思路
对f(x)求导,得f’(x) = 3x^2 - 10x + 10。由一元二次方程求根公式知方程f’(x) = 0无解,因此f’(x) 恒大于0.故f(x)是单调递增的,易知f(0) < 0且f(100) > 0,所以区间[0,100]内必然有且只有一个根。由于f(x)在[0,100]内是单调的,所以可以用二分法在区间[0,100]中寻找根。
解答
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
double EPS = 1e-6;
double f(double x) {
return x*x*x - 5*x*x + 10*x - 80;
}
int main() {
double root, x1 = 0, x2 = 100, y;
root = x1+(x2-x1)/2;
int triedTimes = 1; // 记录一共尝试了多少次,对求根来说不是必须的
y = f(root);
while (fabs(y) > EPS) {
if (y > 0)
x2 = root;
else
x1 = root;
root = x1+(x2-x1)/2;
y = f(root);
triedTimes++;
}
printf("%.8f\n", root);
printf("%d\n", triedTimes);
return 0;
}
寻找指定和的整数对
题目描述
输入n ( n<= 100,000)个整数,找出其中的两个数,它们之和等于整数m(假定肯定有解)。题中所有整数都能用 int 表示。
解题思路
解法1:用两重循环,枚举所有的取数方法,复杂度是O(n 2 )的。
for(int i = 0;i < n-1; ++i)
for(int j = i + 1; j < n; ++j)
if( a[i]+a[j] == m)
break;
100,000^2 = 100亿,在各种OJ上提交或参加各种程序设计竞赛,这样的复杂度都会超时 !
解法2:
1. 将数组排序,复杂度是O(n*log(n))
2. 对数组中的每个元素a[i],在数组中二分查找m-a[i],看是否能找到。复杂度O(log(n)),最坏要查找n-1次,所以查找这部分的复杂度也是O(n*log(n))
这种解法总的复杂度是O(n*log(n))的。
解法3:
1. 将数组排序,复杂度是O(n*log(n))
2. 查找的时候,设置两个变量i和j,i初始值是0,j初始值是n-1,看a[i] + a[j],如果大于m,就让j减1,如果小于m,就让i加1,直到a[i] + a[j] = m。
这种解法总的复杂度是O(n*log(n))的。
查找学生信息
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct Student {
char id[100];
char name[100];
char sex[5];
int age;
bool operator < (const Student& A) const {
return strcmp(id, A.id) < 0;
}
} stu[1005];
int main() {
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 0; i < n; i++) {
scanf("%s%s%s%d", stu[i].id, stu[i].name, stu[i].sex, &stu[i].age);
}
sort(stu, stu+n);
int t;
scanf("%d", &t);
while (t--) {
int ans = -1;
char x[30];
scanf("%s", x);
int low = 0, high = n-1;
while (low <= high) {
int mid = low + (high-low)/2;
int tmp = strcmp(stu[mid].id, x);
if (tmp == 0) {
ans = mid;
break;
} else if (tmp > 0)
high = mid - 1;
else
low = mid + 1;
}
if (ans == -1)
printf("No Answer!\n");
else
printf("%s %s %s %d\n", stu[ans].id, stu[ans].name, stu[ans].sex, stu[ans].age);
}
}
return 0;
}