title: 求包含每个有序数组(共k个)至少一个元素的最小区间

toc: false

date: 2018-09-22 21:03:22

categories:

  • OJ

tags:

  • 归并

给定k个有序数组, 每个数组有个N个元素,找出一个最小的闭区间,使其包含每个数组中的至少一个元素。

关于最小区间——

给定两个区间[a,b], [c,d]:

如果 b-a < d-c,则认为[a, b]是更小的区间;

如果 b-a == d-c,且a < c,则认为[a, b]是更小的区间。

不妨设k为3,分别为a,b,c数组且a1<=b1<=c1,当前最小区间长度为INT_MAX

假设三个数组所有元素排序后为:

a1,...,b1,...,c1,.....

我们考虑最小的a1,若最小区间包含的a数组的元素为a1,则若[a1,c1]的长度小于当前最小区间长度,更新最小区间长度为c1-a1,

然后我们丢弃a1,因为若最小区间包含的a数组元素为a1,则最小区间一定为[a1,c1],而我们已经更新了这个长度;若不是a1,则丢弃a1也无关紧要,不影响最后结果。

那么现在我们一直的最小区间长度为c1-a1,三个数组剩下所有元素排序后可能为

a2,..,b1,..,c1,...或

b1,..,a2,..c1,...或

b1,..,c1,..a2...

第一种情况就类似于上边讨论的情况,更新最小区间长度为c1-a2,然后丢弃a2。

对于后两种情况,我们考虑最小的b1:

若最小区间包含的b数组的元素为b1,则最小区间包含的一定为b1,c1,a2,我们更新最小区间长度,然后丢弃b1,

若不是b1,则丢弃b1;

这样不断循环地考虑最小值,直到丢弃完了某一个数组的所有值,这样我们的当前最小区间长度就是所求结果。

下边是代码:

#include <iostream>
#include <limits.h>
#include <vector>
using namespace std; int main() {
int k, n;
cin>>k>>n;
if (k <= 0 || n <= 0) return 0;
vector<vector<int> > nums;
vector<int> pos;
for (int i = 0; i < k; i++) {
vector<int> arrayI;
int tmp;
for (int j = 0; j < n; j++) {
cin>>tmp;
arrayI.push_back(tmp);
}
nums.push_back(arrayI);
pos.push_back(0);
}
int minLength = INT_MAX;
int realMin, realMax;
while (true) {
int arrayOfLeastNum = -1;
int tmpMin = INT_MAX;
int tmpMax = INT_MIN;
for (int i = 0; i < k; i++) {
if (nums[i][pos[i]] < tmpMin) {
tmpMin = nums[i][pos[i]];
arrayOfLeastNum = i;
}
if (nums[i][pos[i]] > tmpMax) {
tmpMax = nums[i][pos[i]];
}
}
if (tmpMax - tmpMin < minLength) {
minLength = tmpMax - tmpMin;
realMin = tmpMin, realMax = tmpMax;
}
if (++pos[arrayOfLeastNum] >= n) break;
}
cout<<realMin<<' '<<realMax;
return 0;
}

但是,这个只能过90%:

运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。

case通过率为90.00%

看了一下题下的讨论,可以用一个优先队列(priority_queue,一个STL)或自己实现一个最小堆来维护“当前最小区间队列”,这样查找当前的最大值和最小值就是O(logn)而不是O(n)

下边帖一下别人的代码:

链接:https://www.nowcoder.com/questionTerminal/0399d363fb594970bae7ad8a3978f86a
来源:牛客网 //思路2,用优先队列去实现多路归并 #include<bits/stdc++.h>
using namespace std;
struct pt{
int x;
int pos;
pt(int a,int b):x(a),pos(b){}
};
struct cmp{ //重写比较函数
bool operator()(const pt a,const pt b){
return a.x>b.x;
}
};
int main(){
int k,n;
while(cin>>k>>n){
vector<vector<pt>>all;
vector<int> vec;
for(int i = 0;i<k;i++){
vector<pt>temp;
for(int j = 0;j<n;j++){
int x;
cin>>x;
pt p(x,i);
temp.push_back(p);
}
all.push_back(temp);
vec.push_back(0);
}
vector<pt> sort;
priority_queue<pt,vector<pt>,cmp> qu; //优先队列
for(int i = 0;i<k;i++)
qu.push(all[i][0]);
while(!qu.empty()){
pt temp = qu.top();
qu.pop();
sort.push_back(temp);
vec[temp.pos]++;
if(vec[temp.pos]<=n-1){
qu.push(all[temp.pos][vec[temp.pos]]);
}
}
for(int i = 0;i<vec.size();i++)
vec[i] = 0;
int begin = 0;
int end = 0;
int start = 0;
int final = 0;
int length = INT_MAX;
bool flg = false;
vec[sort[0].pos]++;
while(begin<sort.size()-1||end<sort.size()-1){
bool flgg = true;
for(int i = 0;i<k;i++)
flgg = flgg&&(vec[i]>=1);
if(!flgg&&end<sort.size()){
if(end<sort.size()-1)
end++;
vec[sort[end].pos]++;
}
if(!flgg&&end==sort.size()-1)
break;
if(flgg&&begin<sort.size()){
int x = sort[end].x-sort[begin].x;
if(x<length){
start = sort[begin].x;
final = sort[end].x;
length = x;
}
vec[sort[begin].pos]--;
if(begin<sort.size()-1)
begin++;
}
int a = 1;
}
cout<<start<<" "<<final<<endl;
}
system("pause");
return 0;
}

求包含每个有序数组(共k个)至少一个元素的最小区间的更多相关文章

  1. 求两个有序数组的中位数或者第k小元素

    问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...

  2. Codeforces Round #283 (Div. 2) A. Minimum Difficulty【一个数组定义困难值是两个相邻元素之间差的最大值。 给一个数组,可以去掉任意一个元素,问剩余数列的困难值的最小值是多少】

    A. Minimum Difficulty time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  3. 【递归打卡2】求两个有序数组的第K小数

    [题目] 给定两个有序数组arr1和arr2,已知两个数组的长度分别为 m1 和 m2,求两个数组中的第 K 小数.要求时间复杂度O(log(m1 + m2)). [举例] 例如 arr1 = [1, ...

  4. 求两个有序数组的中位数(4. Median of Two Sorted Arrays)

    先吐槽一下,我好气啊,想了很久硬是没有做出来,题目要求的时间复杂度为O(log(m+n)),我猜到了要用二分法,但是没有想到点子上去.然后上网搜了一下答案,感觉好有罪恶感. 题目原型 正确的思路是:把 ...

  5. [LeetCode] 632. Smallest Range Covering Elements from K Lists 覆盖K个列表元素的最小区间

    You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...

  6. JS数组at函数(获取最后一个元素的方法)介绍

    本文介绍js中数组的at函数,属于比较简单的知识普及性文章,难度不大. 0x00 首先,我们可以思考如下一个问题,如果要获取一个数组的最后一个元素(这是很常用的操作),我们应该怎么做? 相信大部分人能 ...

  7. 算法-求两个有序数组两两相加的值最小的K个数

    我的思路是: 用队列,  从(0,0)開始入队,每次出队的时候,选(1,0) (0,1) 之间最小的入队,假设是相等的都入队,假设入过队的就不入了,把出队的k个不同的输出来就可以 我測试了几组数据都是 ...

  8. Median of Two Sorted 求两个有序数组的中位数

    中位数是把一个数的集合划分为两部分,每部分包含的数字个数相同,并且一个集合中的元素均大于另一个集合中的元素. 因此,我们考虑在一个任意的位置,将数组A划分成两部分.i表示划分数组A的位置,如果数组A包 ...

  9. 给定一个值S,在有序数组中找出两个元素A和B,使 A+B = S.

    在网上看到过一个面试题,感觉挺有意思,看别人的代码写的逻辑不够谨慎,重写了一个,较真了又... package com.array7.algorithm; public class Algorithm ...

随机推荐

  1. 关于FastIo

    由于你的驱动将要绑定到文件系统驱动的上边,文件系统除了处理正常的IRP 之外,还要处理所谓的FastIo.FastIo是Cache Manager 调用所引发的一种没有irp 的请求.换句话说,除了正 ...

  2. wordcloud + jieba 生成词云

    利用jieba库和wordcloud生成中文词云. jieba库:中文分词第三方库 分词原理: 利用中文词库,确定汉字之间的关联概率,关联概率大的生成词组 三种分词模式: 1.精确模式:把文本精确的切 ...

  3. java exception 异常错误记录

    //异常:Could not obtain transaction-synchronized Session for current thread 做定时器的时候用ApplicationContext ...

  4. Array.of()和Array()区别

    Array.of方法用于将一组值,转换为数组. Array.of(3, 11, 8) // [3,11,8] Array.of(3) // [3] Array.of(3).length // 1 这个 ...

  5. 基于 Web 的 Go 语言 IDE - Wide 1.4.0 发布!

    Wide 是什么 Wide 是一个基于 Web 的 Go 语言团队 IDE . 在线开发:打开浏览器就可以进行开发.全快捷键 智能提示:代码自动完成.查看表达式.编译反馈. Lint 实时运行:极速编 ...

  6. 解决启动httpd报: apr_sockaddr_info_get() failed for错误

    我测试库里 service httpd start 时报 下面错误 httpd: apr_sockaddr_info_get() failed for fengxin.wzjzt.centoshttp ...

  7. java equals的用法

    equals方法,用于比较两个对象是否相同,它其实就是使用两个对象的内存地址在比较.Object类中的equals方法内部使用的就是==比较运算符. package Xuexi; public cla ...

  8. Teradata在大数据管理与分析领域连续18年评测排名第一

    Gartner 魔力象限介绍 Gartner(高德纳)全球最具权威的IT市场研究与顾问咨询公司,他总是不停地推出IT行业的各种报告以及著名的Gartner魔力象限. Gartner魔力象限通常从两个方 ...

  9. 【udacity】机器学习-2模型验证

    Evernote Export 1.模型的评估与验证简介 机器学习通常是大量传入数据,然后会有一些关于数据的决策.想法和摘要. 2.模型评估 评估模型使用的是各种数据分析的方法,至少需要使用pytho ...

  10. 训练1-C

    妈妈每天都要出去买菜,但是回来后,兜里的钱也懒得数一数,到底花了多少钱真是一笔糊涂帐.现在好了,作为好儿子(女儿)的你可以给她用程序算一下了,呵呵. Input 输入含有一些数据组,每组数据包括菜种( ...