求包含每个有序数组(共k个)至少一个元素的最小区间
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个)至少一个元素的最小区间的更多相关文章
- 求两个有序数组的中位数或者第k小元素
问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...
- 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 ...
- 【递归打卡2】求两个有序数组的第K小数
[题目] 给定两个有序数组arr1和arr2,已知两个数组的长度分别为 m1 和 m2,求两个数组中的第 K 小数.要求时间复杂度O(log(m1 + m2)). [举例] 例如 arr1 = [1, ...
- 求两个有序数组的中位数(4. Median of Two Sorted Arrays)
先吐槽一下,我好气啊,想了很久硬是没有做出来,题目要求的时间复杂度为O(log(m+n)),我猜到了要用二分法,但是没有想到点子上去.然后上网搜了一下答案,感觉好有罪恶感. 题目原型 正确的思路是:把 ...
- [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 ...
- JS数组at函数(获取最后一个元素的方法)介绍
本文介绍js中数组的at函数,属于比较简单的知识普及性文章,难度不大. 0x00 首先,我们可以思考如下一个问题,如果要获取一个数组的最后一个元素(这是很常用的操作),我们应该怎么做? 相信大部分人能 ...
- 算法-求两个有序数组两两相加的值最小的K个数
我的思路是: 用队列, 从(0,0)開始入队,每次出队的时候,选(1,0) (0,1) 之间最小的入队,假设是相等的都入队,假设入过队的就不入了,把出队的k个不同的输出来就可以 我測试了几组数据都是 ...
- Median of Two Sorted 求两个有序数组的中位数
中位数是把一个数的集合划分为两部分,每部分包含的数字个数相同,并且一个集合中的元素均大于另一个集合中的元素. 因此,我们考虑在一个任意的位置,将数组A划分成两部分.i表示划分数组A的位置,如果数组A包 ...
- 给定一个值S,在有序数组中找出两个元素A和B,使 A+B = S.
在网上看到过一个面试题,感觉挺有意思,看别人的代码写的逻辑不够谨慎,重写了一个,较真了又... package com.array7.algorithm; public class Algorithm ...
随机推荐
- lua闭包函数
function createCountdownTimer(second) local ms = second * local function countDown() ms = ms - retur ...
- angular实现的tab栏切换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Java单例模式 多种实现方式
一:通过静态私有成员实现单例模式 (1):私有化构造函数 (2):new静态实例属性对象,加锁. 单例类: package SinglePag; /* * 构造函数私有化,结合锁+静态的概念 实现单例 ...
- vue 脚手架 使用步骤
当我知道搭建脚手架得使用命令行的时候.我就崩溃了.所以写一篇记录以后留着自己用也方便大家. 首先要安装一个node 环境, 1.打开cmd 进到你要建项目的目录: E: ...
- 转载:关于 python ImportError: No module named 的问题
关于 python ImportError: No module named 的问题 今天在 centos 下安装 python setup.py install 时报错:ImportError: N ...
- .bat 打开程序
为什么要用.bat打开程序. 因为一个一个难得点 怎么做 百度的,start 程序路径\程序 改进 点击bat,不显示dos窗口. 新建.vbs文件 Set shell = Wscript.creat ...
- 在maven项目结构下对于Resources目录下文件的存取
在maven项目中,文件结构如下: proj ---src ----main ----java ----Main.java ----resources ----userFile.properties ...
- layer弹出框的用法
页面中引入 layer.js 就行了 1.弹出一个提示信息: layer.msg("我是哦提示信息"); 2.弹出一个带选择的按钮的框 layer.open({ title: ' ...
- 为my_string类创建复制构造函数copy constructor ,拷贝函数名和类同名
为下面的my_string类创建一个复制构造函数,并将定义该类的代码提交. my_string类的定义: class my_string { char *s; public: my_string(ch ...
- vue组件通信,点击传值,动态传值(父传子,子传父)
转载:https://blog.csdn.net/xr510002594/article/details/83304141 一.父组件传子组件,核心--props 在这里触发 handleClick ...