一、最小区间
题目描述
给定k个有序数组, 每个数组有个N个元素,找出一个最小的闭区间,使其包含每个数组中的至少一个元素。
给定两个区间[a,b], [c,d]:
如果 b-a < d-c,则认为[a, b]是更小的区间;
如果 b-a == d-c,且a < c,则认为[a, b]是更小的区间。
输入描述:
K N x11 x12 x13 ... x1n ... xk1 xk2 xk3 ... xkn
输出描述:
两个数,分别为最小区间的左右边界
示例1
输入
3 3 2 12 14 2 6 9 4 7 19
输出
2 4
二、最小区间 - 敲代码
1、将k个序列分别排序;
2、维护一个k个元素的数组 st;
3、每次从k个序列中(序列头部)取一个最小的元素(在原序列中删除该元素),替换 st 中对应位置的元素,计算 st 的区间大小,更新 [minst, maxst] 区间结果。
4、只能过90%。
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <climits>
using namespace std;
int main()
{
int k, n;
cin >> k >> n;
vector<deque<int>> num(k, deque<int>(n));
for (int i = 0; i < k; i++)
{
for (int j = 0; j < n; j++)
{
cin >> num[i][j];
}
//sort(num[i].begin(), num[i].end()); //排序
}
vector<int> st(k);
int minst = INT_MAX; //[,区间左边界
int maxst = INT_MIN; //],区间右边界
//初始第一列
for (int j = 0; j < k; j++)
{
st[j] = num[j][0];
num[j].pop_front();
minst = min(minst, st[j]);
maxst = max(maxst, st[j]);
}
int minlen = maxst - minst; //[]
//之后每次从所有列头元素中取最小的一个
int min_st = minst;
int max_st = maxst;
for (int i = k; i < k*n; i++)
{
//检查最小元素的位置j
int minnum = INT_MAX;
int index = -1;
for (int j = 0; j < k; j++)
{
if (!num[j].empty() && num[j][0] < minnum)
{
minnum = num[j][0];
index = j;
}
}
//插入新元素
if (index != -1)
{
st[index] = num[index][0]; //j位置替换
num[index].pop_front(); //j行出队头
//更新区间大小
min_st = *min_element(st.begin(), st.end());
max_st = *max_element(st.begin(), st.end());
int diff = max_st - min_st;
if (diff < minlen)
{
minlen = max_st - min_st;
minst = min_st;
maxst = max_st;
}
}
}
cout << minst << ' ' << maxst;
return 0;
}