我需要你的帮助,我有一个问题(见图),我已经说过两个数组,每个数组都包含不同长度和实际值的区间,我需要找出我是如何重叠这个区间的有效。
我对创意,纸质理论或混凝土算法持开放态度,让我找到出路! 我猜想要以某种方式在波浪中转换它并重叠它们。
非常重要,它适用于我的论文。
作为一个例子,在这里用数字来解释它更好:
结果将是一个包含新间隔的单个数组。
第二个间隔(第一和第二个数组)重叠。
结果数组:1-2,3-4,5-7,9-12,13-17
我正在考虑“间隔树”,但它还不足以让我合并它们。
提前致谢!
答案 0 :(得分:10)
1)将所有间隔放在一个数组中。
2)按每个区间的下限对该数组进行排序。
3)循环从最低下限到最高上限的区间:
a)如果此结束之后的时间间隔在此结束之前开始,则合并它们(删除第二个并将其扩展为其上限)。
b)重复此操作结束后,重复下一个间隔开始。
4)重复直到你到达最后一个间隔。
答案 1 :(得分:3)
这是python中的一个版本(版本2和3):
def aggregate(data):
data.sort()
i = 0
while i < len(data) - 1:
while i < len(data) - 1 and data[i][1] >= data[i+1][0]:
data[i] = (data[i][0], max(data[i][1], data[i+1][1]))
data.pop(i+1)
i += 1
if __name__ == '__main__':
itervals = [(1,2), (5,7), (9,12), (3,4), (5,6), (13,17)]
formatted = lambda vals: '[{}]'.format(', '.join('({}-{})'.format(
iterval[0], iterval[1])
for iterval in sorted(vals)))
print(formatted(itervals))
aggregate(itervals)
print(formatted(itervals))
输出:
[(1-2), (3-4), (5-6), (5-7), (9-12), (13-17)]
[(1-2), (3-4), (5-7), (9-12), (13-17)]
注意:这会在适当的位置改变元组列表。可以通过更改行来完成稍微更通用的一个,它将与迭代列表一起使用:
data[i] = type(data[i])((data[i][0], max(data[i][1], data[i+1][1])))
或者,如果您知道可变迭代的列表,则可以使用:
data[i][1] = max(data[i][1], data[i+1][1])
可能更容易理解的替代版本是:
def aggregate(data):
if not data:
return data
inputs = sorted(data)
result = [inputs[0]]
for next0, next1 in inputs[1:]:
last0, last1 = result[-1]
if next0 <= last1:
result[-1][1] = max(next1, last1)
else:
result.append([next0, next1])
return result
请注意,此列表是为列表清单而设计的。
答案 2 :(得分:1)
#include <vector>
using namespace std;
struct INTERVAL {
int a;
int b;
};
// v is a sorted vector of intervals (a<=b)
// i is an interval (a<=b) to be merged with v,
vector<INTERVAL> merge(vector<INTERVAL>& v, INTERVAL& i)
{
bool fMerged=false; // merged flag
INTERVAL r=i; // merged interval
vector<INTERVAL> out; // out vector
vector<INTERVAL>::size_type k=0; // iterator
for(k=0; k<v.size(); ++k) {
if (fMerged || v[k].b < r.a) {
out.push_back(v[k]); // v[k] comes first
}
else if (r.b<v[k].a) {
out.push_back(r); // r comes first
out.push_back(v[k]);
fMerged=true; // copy rest;
}
else { // intervals overlap, merge into r
r.a=min(v[k].a,r.a);
r.b=max(v[k].b,r.b);
}
}
// interval not merged, append to vector
if (!fMerged) out.push_back(r);
return out;
}
这可能是一种方法
答案 3 :(得分:0)
/**
* sort the interval based on the start time
* push the first interval to stack
* compare each interval start time with end time of top of stack
* if interval i th start time is more than than start and end time of top of stack
* do nothing
* if interval i th start time is between start and end time of top of stack then
* update top of stack with ith interval end time
*
*/
import java.util.Stack;
import java.util.Arrays;
public class MergeInterval{
private static Stack<Interval> st = new Stack<Interval>();
class Interval implements Comparable<Interval>{
public int startTime;
public int endTime;
public Interval(int startTime, int endTime){
this.startTime=startTime;
this.endTime=endTime;
}
@Override
public int compareTo(Interval i){
if(startTime <=i.startTime) return 0;
return 1;
}
public boolean canMerge(Interval m){
if((startTime<=m.startTime) && (endTime>=m.startTime)) return true;
else return false;
}
public String toString(){
return ("{ "+startTime+" , "+endTime+" } ");
}
}
private static void findOverlapping(Interval[] setOne){
//System.out.println(Arrays.toString(setOne));
Arrays.sort(setOne);
//System.out.println(Arrays.toString(setOne));
st.push(setOne[0]);
for(int i=1;i<setOne.length;i++){
Interval in = st.peek();
if(in.canMerge(setOne[i])){
in.endTime=setOne[i].endTime;
}else{
st.push(setOne[i]);
}
}
System.out.println(Arrays.toString(st.toArray()));
}
public static void main(String[] args) {
MergeInterval m = new MergeInterval();
Interval[] setOne = m.populate();
findOverlapping(setOne);
}
public Interval[] populate(){
Interval[] setOne = new Interval[4];
for(int i=0;i<4;i++){
setOne[i]=new Interval(1,3);
}
setOne[0]=new Interval(1,3);
setOne[1]=new Interval(2,4);
setOne[2]=new Interval(5,7);
setOne[3]=new Interval(6,8);
return setOne;
}
}
答案 4 :(得分:0)
# Python implementation of http://www.geeksforgeeks.org/merging-intervals/
# Expects a list of (start,end) tuples
def merge_intervals(a):
# Handle empty list correctly
if len(a) == 0:
return []
# Operate on a copy so the original array is left untouched
a = list(a)
# Sort by lower bound
a.sort()
# Create stack from first interval
b = [ a[0] ]
# Loop through remaining intervals - either merge with top of stack or add
for idx in xrange(1, len(a)):
# References to top of stack and current in loop
previous, current = b[-1], a[idx]
# New interval if not overlapping
if previous[1] < current[0]:
b.append( current )
# Merge if overlapping (if expands interval)
elif previous[1] < current[1]:
b.pop()
b.append(( previous[0], current[1] ))
# Return list of merged intervals
return b
# Test case
if __name__ == '__main__':
data = [ (1,5), (2,3), (4,6), (7,10), (8,12) ]
from random import shuffle
shuffle(data)
print 'BEFORE', data
data = merge_intervals(data)
print 'AFTER', data
答案 5 :(得分:0)
JAVA版本完成此任务:Source documenation
public class MergeRange {
public class Range{
public int start;
public int end;
public Range(int s, int e){
start = s;
end = e;
}
@Override
public String toString() {
return "[" + start + "," + end + "]";
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Range)) {
return false;
}
Range c = (Range) o;
return start == c.start && end == c.end;
}
}
//compare two range by start, used to sort list of ranges by their starts
public class RangeComparator implements Comparator<Range> {
public int compare(Range range1, Range range2) {
return Integer.compare(range1.start, range2.start);
}
}
public List<Range> merge(List<Range> ranges){
if (ranges.size() < 2){
return ranges;
}
ranges.sort(new RangeComparator());
List<Range> result = new ArrayList<Range>();
result.add(ranges.get(0));
for (int i = 1; i < ranges.size(); i++){
Range lastAdded = result.get(result.size() - 1);
result.remove(result.size() - 1);
List<Range> newRanges = merge(lastAdded, ranges.get(i));
result.addAll(newRanges);
}
return result;
}
//merge two ranges where range1.start <= range2.start
private List<Range> merge(Range range1, Range range2){
Assert.assertTrue(range1.start <= range2.start);
if (range1.end < range2.start){
return Arrays.asList(range1, range2);
} else{
Range result = new Range(range1.start, Math.max(range1.end, range2.end));
return Arrays.asList(result);
}
}
}