解题思路
这是一道关于区间选择的问题。主要思路如下:
-
问题分析:
- 给定
个有序数组,每个数组有
个元素
- 需要找出一个最小区间
- 该区间包含每个数组中的至少一个元素
- 给定
-
优化思路:
- 使用优先队列维护当前最小值
- 记录每个数组的当前位置
- 动态维护区间的最大值
- 每次更新时比较新区间和当前最优区间
-
关键点:
- 使用结构体存储元素值和来源数组
- 优先队列保证获取最小值的效率
- 正确维护区间的最大值
代码
#include<bits/stdc++.h>
using namespace std;
// 定义节点结构
struct node {
int x, type; // x为值,type为数组编号
node(int x, int type):x(x),type(type){}
};
// 定义优先队列的比较函数
struct cmp {
bool operator()(const node& a, const node& b)const {
return a.x > b.x;
}
};
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int k, n;
cin >> k >> n;
// 存储所有数组,下标从1开始
vector<vector<int>> a(k+1, vector<int>(n+1));
for(int i = 1; i <= k; ++i) {
for(int j = 1; j <= n; ++j) {
cin >> a[i][j];
}
}
priority_queue<node, vector<node>, cmp> px;
// 初始化:取每个数组的第一个元素
int mi = a[1][1], ma = a[1][1];
for(int i = 1; i <= k; ++i) {
a[i][0] = 1; // 记录当前位置
node tmp = {a[i][1], i};
px.push(tmp);
mi = min(mi, tmp.x);
ma = max(ma, tmp.x);
}
int maa = ma; // 维护当前最大值
// 当优先队列中元素个数等于k时继续
while(px.size() == k) {
node tmp = px.top();
px.pop();
int type = tmp.type;
// 如果当前数组还有元素
if(a[type][0] < n) {
node add = {a[type][++a[type][0]], type};
px.push(add);
int mii = px.top().x;
maa = max(maa, add.x);
// 更新最优区间
if(maa - mii < ma - mi) {
mi = mii;
ma = maa;
}
}
}
cout << mi << " " << ma << endl;
return 0;
}
import java.util.*;
class Node {
int x, type;
Node(int x, int type) {
this.x = x;
this.type = type;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
int n = sc.nextInt();
int[][] a = new int[k+1][n+1];
int[] pos = new int[k+1]; // 记录每个数组的当前位置
// 读入数据
for(int i = 1; i <= k; i++) {
for(int j = 1; j <= n; j++) {
a[i][j] = sc.nextInt();
}
}
// 创建优先队列
PriorityQueue<Node> pq = new PriorityQueue<>((x, y) -> x.x - y.x);
// 初始化
int mi = a[1][1], ma = a[1][1];
for(int i = 1; i <= k; i++) {
pos[i] = 1;
Node node = new Node(a[i][1], i);
pq.offer(node);
mi = Math.min(mi, node.x);
ma = Math.max(ma, node.x);
}
int maa = ma;
while(pq.size() == k) {
Node curr = pq.poll();
int type = curr.type;
if(pos[type] < n) {
Node next = new Node(a[type][++pos[type]], type);
pq.offer(next);
int mii = pq.peek().x;
maa = Math.max(maa, next.x);
if(maa - mii < ma - mi) {
mi = mii;
ma = maa;
}
}
}
System.out.println(mi + " " + ma);
}
}
from heapq import *
class Node:
def __init__(self, x, type):
self.x = x
self.type = type
def __lt__(self, other):
return self.x < other.x
k = int(input())
n = int(input())
a = [[0] * (n+1) for _ in range(k+1)]
pos = [1] * (k+1) # 记录每个数组的当前位置
# 读入数据
for i in range(1, k+1):
row = list(map(int, input().split()))
for j in range(1, n+1):
a[i][j] = row[j-1]
# 初始化优先队列
pq = []
mi = ma = a[1][1]
for i in range(1, k+1):
node = Node(a[i][1], i)
heappush(pq, node)
mi = min(mi, node.x)
ma = max(ma, node.x)
maa = ma
while len(pq) == k:
curr = heappop(pq)
type = curr.type
if pos[type] < n:
pos[type] += 1
next_node = Node(a[type][pos[type]], type)
heappush(pq, next_node)
mii = pq[0].x
maa = max(maa, next_node.x)
if maa - mii < ma - mi:
mi = mii
ma = maa
print(mi, ma)
复杂度分析
- 时间复杂度:
- 每个元素最多入队一次
- 每次堆操作需要
- 空间复杂度:
- 存储原始数组
- 优先队列最多存储
个元素