输入n值(1<=n<=1000)、n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数。若x不存在,输出-1和比较次数。
#include
using namespace std;
int count = 0;
//在数组a[left...right]中查找元素x
int biSearch(int x, int a[], int left, int right) {
if (left > right) //当数组中没有元素时
return -1;
count++;
int middle = (left + right) / 2;
if (a[middle] == x) //如果找到,直接返回位置
return middle;
else if (a[middle] > x) //如果中间的数字大于x,在数组左半部分递归查找
returnbiSearch(x, a, left, middle - 1);
else //否则在数组右半部分递归查找
returnbiSearch(x, a, middle + 1, right);
}
int main() {
int n;
cin>> n;
int a[n];
for (inti = 0; i< n; i++)
cin>> a[i];
int x;
cin>> x;
cout<<biSearch(x, a, 0, n - 1) <<endl;
cout<< count <<endl;
}
设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。
#include
using namespace std;
voidbiSearch(int x, int a[], int left, int right) {
if (left > right) { //当数组中没有元素时
cout<< right << " " << left <<endl;
return;
}
int middle = (left + right) / 2;
if (a[middle] == x) {
cout<< middle << " " << middle <<endl;
return;
} else if (a[middle] > x)
returnbiSearch(x, a, left, middle - 1);
else
returnbiSearch(x, a, middle + 1, right);
}
int main() {
int n;
int x;
cin>> n >> x;
int a[n];
for (inti = 0; i< n; i++)
cin>> a[i];
biSearch(x, a, 0, n - 1);
}
已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0,A1,⋯,AN−1的中位数指A(N−1)/2的值,即第⌊(N+1)/2⌋个数(A0为第1个数)。
方法一:
#include
using namespace std;
//查找两个等长有序系列的中位数
/*
解题思路:中位数满足大于且仅大于n-1个元素,小于且仅小于n个元素
a_mid = (a_left + a_right) / 2
b_mid = (b_left + b_right) / 2
当a[a_mid]=b[b_mid]时,中位数为a[a_mid]
当a[mid]b[mid]时:
若n为奇数,中位数存在范围为a[a_left...a_mid], b[b_mid...b_right]
若n为偶数,中位数存在范围为a[a_left...a_mid], b[b_mid+1...b_right]
当问题规模为1时,只有两个数字,直接输出较小的值
*/
int find(int a[], int a_l, int a_r, int b[], int b_l, int b_r) {
int a_m, b_m;
int num;
//如果查找数组包含两个数字,则直接找出中位数
if (a_r == a_l) {
return a[a_l] < b[b_l] ? a[a_l] : b[b_l];
}
//第1个数组查找范围的中位数a_m。
a_m = (a_l + a_r) / 2;
//第2个数组查找范围的中位数b_m。
b_m = (b_l + b_r) / 2;
//如果两个中位数相等,则找到退出
if(a[a_m] == b[b_m])
{
num = a[a_m];
} else if(a[a_m] < b[b_m]) {
//如果n为偶数,右半部分的开始位置为中位数位置加1
if ((a_r - a_l + 1) % 2 == 0)
a_m += 1;
//第1个数组查找范围为右半部分,第2个数组查找范围为左半部分
num = find(a, a_m, a_r, b, b_l, b_m);
}
else {
//如果n为偶数,右半部分的开始位置中位数位置加1
if ((b_r - b_l + 1) % 2 == 0)
b_m += 1;
//第1个数组查找范围为左半部分,第2个数组查找范围为右半部分
num = find(a, a_l, a_m, b, b_m, b_r);
}
return num;
}
int main() {
int n;
cin>> n;
int a[n];//数组1
int b[n];//数组2
for (int i = 0; i< n; i++)
cin>> a[i];
for (int i = 0; i< n; i++)
cin>> b[i];
cout<< find(a, 0, n - 1, b, 0, n - 1) <<endl;
return 0;
}
方法二:
#include
int main(){
intn,m;
scanf("%d",&n);
int a[n],b[n];
for(inti=0; i<n;i++){
scanf("%d",&a[i]);
}
for(inti=0; i<n;i++){
scanf("%d",&b[i]);
}
inta_flag=0,b_flag=0;
while(a_flag+b_flag<n-1){
if(a[a_flag]>=b[b_flag])
b_flag++;
else
a_flag++;
}
m=a[a_flag]>b[b_flag]?b[b_flag]:a[a_flag];
printf("%d",m);
}
第二章作业题
设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。
提示:函数
int partition(int a[],int left,int right)
的功能是根据a[left]~a[right]
中的某个元素x(如a[left])对a[left]~a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数。因此可以编制int find(int a[],int left,int right,int k)
函数,通过调用partition函数获得划分点,判断划分点是否第k小,若不是,递归调用find函数继续在左段或右段查找。
输入格式:
输入有两行:
第一行是n和k,0 第二行是n个整数 输出格式: 输入样例: 10 4 2 注意:本问题算法的时间复杂度要求为O(nlogn), 否则得分无效 题目来源:http://poj.org/problem?id=1804 Background Raymond Babbitt drives his brother Charlie mad. Recently Raymond counted 246 toothpicks spilled all over the floor in an instant just by glancing at them. And he can even count Poker cards. Charlie would love to be able to do cool things like that, too. He wants to beat his brother in a similar task. Problem Here’s what Charlie thinks of. Imagine you get a sequence of N numbers. The goal is to move the numbers around so that at the end the sequence is ordered. The only operation allowed is to swap two adjacent numbers. Let us try an example: Start with: 2 8 0 3 swap (2 8) 8 2 0 3 swap (2 0) 8 0 2 3 swap (2 3) 8 0 3 2 swap (8 0) 0 8 3 2 swap (8 3) 0 3 8 2 swap (8 2) 0 3 2 8 swap (3 2) 0 2 3 8 swap (3 8) 0 2 8 3 swap (8 3) 0 2 3 8 So the sequence (2 8 0 3) can be sorted with nine swaps of adjacent numbers. However, it is even possible to sort it with three such swaps: Start with: 2 8 0 3 swap (8 0) 2 0 8 3 swap (2 0) 0 2 8 3 swap (8 3) 0 2 3 8 The question is: What is the minimum number of swaps of adjacent numbers to sort a given sequence?Since Charlie does not have Raymond’s mental capabilities, he decides to cheat. Here is where you come into play. He asks you to write a computer program for him that answers the question in O(nlogn). Rest assured he will pay a very good prize for it. 输入格式: 输出格式: 输入样例: 6 5 You are a given a unimodal array of n distinct elements, meaning that its entries are in increasing order up until its maximum element, after which its elements are in decreasing order. Give an algorithm to compute the maximum element that runs in O(log n) time. 输入格式: 输出格式: 输入样例: 有函数:f(x)=x 输出格式:x 输入样例: 我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。 我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。 请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。 输入格式: 输出格式: 输入样例: 25.133
输出第k小的数
在这里给出一组输入。例如:
2 8 9 0 1 3 6 7 8 2
输出样例:
在这里给出相应的输出。例如:#include
7-3)求逆序对数目
The first line contains the length N (1 <= N <= 1000) of the sequence; The second line contains the N elements of the sequence (each element is an integer in [-1000000, 1000000]). All numbers in this line are separated by single blanks.
Print a single line containing the minimal number of swaps of adjacent numbers that are necessary to sort the given sequence.
在这里给出一组输入。例如:
-42 23 6 28 -100 65537
输出样例:
在这里给出相应的输出。例如:#include
7-4) maximum number in a unimodal array
An integer n in the first line, 1<= n <= 10000. N integers in the seconde line seperated by a space, which is a unimodal array.
A integer which is the maximum integer in the array
7
1 2 3 9 8 6 5
输出样例:
9#include
7-5)二分法求函数的零点
5
−15x
4
+85x
3
−225x
2
+274x−121 已知f(1.5)>0,f(2.4)<0 且方程f(x)=0 在区间[1.5,2.4] 有且只有一个根,请用二分法求出该根。 提示:判断函数是否为0,使用表达式 fabs(f(x)) < 1e-7
输入格式:
无。
该方程在区间[1.5,2.4]中的根。要求四舍五入到小数点后6位。。
无
输出样例:
无#include
7-6)(选做题)派
第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。 第二行包含N个1到10000之间的整数,表示每个派的半径。
输出每个人能得到的最大的派的体积,精确到小数点后三位。
3 3
4 3 3
输出样例:
在这里给出相应的输出。例如:#include