2388Who’s in the Middle
http://poj.org/problem?id=2388
一道寻找数组中位数的题
首先,最简单的做法,将数组排序,输出N/2
位置的元素即可:
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN (10000+10)
int N = 0;
int main() {
int nums[MAXN];
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> nums[i];
}
sort(nums, nums + N);
cout << nums[N / 2] << endl;
return 0;
}
如果你想练习一下快排:
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN (10000+10)
int partition(int *arr, int left, int right) {
int pivot = arr[left];
while (left < right) {
while (left < right && arr[right] >= pivot) {
right--;
}
arr[left] = arr[right];
while (left < right && arr[left] <= pivot) {
left++;
}
arr[right] = arr[left];
}
arr[left] = pivot;
return left;
}
void quick_sort(int *arr, int left, int right) {
if (left >= right) {
return;
}
int p = partition(arr, left, right);
quick_sort(arr, left, p - 1);
quick_sort(arr, p + 1, right);
}
int N = 0;
int main() {
int nums[MAXN];
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> nums[i];
}
quick_sort(nums, 0, N - 1);
cout << nums[N / 2] << endl;
return 0;
}
借用快排的思路,当调用partition()
得到的p偏左时,去右子列寻找中位数,否则,去左子列寻找中位数。这样就不用将数组全部排序了:
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN (10000+10)
int partition(int *arr, int left, int right) {
int pivot = arr[left];
while (left < right) {
while (left < right && arr[right] >= pivot) {
right--;
}
arr[left] = arr[right];
while (left < right && arr[left] <= pivot) {
left++;
}
arr[right] = arr[left];
}
arr[left] = pivot;
return left;
}
int N = 0;
int find_mid(int *arr, int left, int right) {
int mid = (left + right) / 2;
while (1) {
int p = partition(arr, left, right);
if (p == N / 2) {
return arr[p];
} else if (p > (N / 2)) {
right = p - 1;
} else {
left = p + 1;
}
}
}
int main() {
int nums[MAXN];
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> nums[i];
}
int ret = find_mid(nums, 0, N - 1);
cout << ret << endl;
return 0;
}
或者利用堆,将全部元素压入堆,弹出N/2-1
个元素后堆顶元素即为所求:
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int N;
int main() {
priority_queue<int> pq;
cin >> N;
int t;
for (int i = 0; i < N; ++i) {
cin >> t;
pq.push(t);
}
for (int i = 0; i < N / 2; ++i) {
pq.pop();
}
cout << pq.top() << endl;
return 0;
}
2456Aggressive cows
http://poj.org/problem?id=2456
采用贪心+二分的策略解决:首先要想到将最值问题转化为判定性问题,通过二分枚举一个个可能的结果,当枚举的间距太大时,向左缩小区间寻找解;当枚举的间距满足条件,贪心地向右缩小区间寻找更优的解
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN (100000+10)
int N;
int C;
int X[MAXN];
bool check(int d) {
int cnt = 0;
int front = 0;
for (int i = 1; i < N; ++i) {
if (X[i] - X[front] >= d) {
cnt++;
front = i;
}
}
return cnt >= (C - 1);
}
int main() {
cin >> N >> C;
for (int i = 0; i < N; ++i) {
cin >> X[i];
}
if (N == 2) {
cout << X[1] - X[0] << endl;
return 0;
}
sort(X, X + N);
int l = 0;
int r = X[N - 1];
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid)) {
l = mid + 1;
} else {
r = mid - 1;
}
}
cout << r << endl;
return 0;
}