我有范围让我们说
如本示例所示,20-40和30-50相交而不是存储两者我需要将其存储为20-50。
然后我想要55-90而不是55-65,65-80和75-90。
所以结果集就像这样
我在redis中有这些值,我在Java中存储它们的结构是数组,一个起始数组和一个结束数组。
我的解决方案:
for int i =0; i< length-1 ; i++
for int j=i+1;j<length; j++
if start[i] <= start[j] && end[i] >= start[j]
store the min max in start and end array and remove the other two entries and proceed
我发现这是因为O(n log n)有没有更好的算法来做到这一点?
Java和redis中的数据结构中的任何建议以及处理此方法的方法或算法都会很棒。
谢谢
答案 0 :(得分:1)
来自文档:
选择支持
add(Range)
操作的实现需要忽略空范围并合并连接的范围。
应用于您的示例:
public static void main(String args[]) {
final RangeSet<Integer> ranges = TreeRangeSet.create();
ranges.add(Range.closed(1, 10));
ranges.add(Range.closed(20, 40));
ranges.add(Range.closed(30, 50));
ranges.add(Range.closed(55, 65));
ranges.add(Range.closed(65, 80));
ranges.add(Range.closed(75, 90));
ranges.add(Range.closed(95, 100));
System.out.println(ranges);
}
输出:
[[1‥10],[20‥50],[55‥90],[95‥100]]
作为Range
和TreeRangeSet
implements Serializable
,您可以按原样将它们保存到Redis。
答案 1 :(得分:1)
如果间隔按起始位置排序,则有一种非常简单的线性算法来合并间隔。排序需要O(nlogn)
,因此总体时间复杂度相同。如果输入没有排序,我相信一般算法仍然需要O(nlogn)
。排序通常更快,因为它与一个小常量相关联。这是更有效的解决方案。
这是javascript中的一个实现,只是为了给你一个想法。您可以转换为java或使用node.js运行它:
function merge_intervals(a)
{ // this function save the result IN PLACE
if (a.length == 0) return;
var st = a[0][0], en = a[0][1], k = 0;
for (var i = 1; i < a.length; ++i) {
if (a[i][0] > en) { // a new interval
a[k++] = [st, en];
st = a[i][0], en = a[i][1];
} else en = a[i][1] > en? a[i][1] : en;
}
a[k++] = [st, en]; // add the last interval
a.length = k; // discard the rest
}
// intervals are half-close-half-open, like C arrays
var a = [[1,10], [20,40], [30,50], [55,65], [65,80], [75,90], [95,100]];
// sort the intervals based on start positions
a.sort(function(x,y) { return x[0]-y[0] });
merge_intverals(a);
for (var i = 0; i < a.length; ++i)
console.log(a[i].join("\t"));
答案 2 :(得分:0)
我认为范围可能并不总是有序。当然,代码可能不是最好的,但它是功能性的
import java.util.*;
class Interval {
int lo;
int hi;
Interval() {
lo = 0;
hi = 0;
}
Interval(int lo, int hi) {
this.lo = lo;
this.hi = hi;
}
@Override
public String toString() {
return "[" + lo + "," + hi + "]";
}
}
public class Demo {
public static ArrayList<Interval> merge(ArrayList<Interval> list) {
Collections.sort(list, new Comparator<Interval>() {
public int compare(Interval i1, Interval i2) {
if (i1.lo == i2.lo) {
return i1.hi - i2.hi;
}
return i1.lo - i2.lo;
}
});
System.out.println("Sorted Input: " + list);
ArrayList<Interval> result = new ArrayList<Interval>();
Interval prev = list.get(0);
result.add(prev);
for (int i = 1; i < list.size(); i++) {
Interval current = list.get(i);
if (prev.hi >= current.lo) {
Interval Interval = new Interval(prev.lo, Math.max(prev.hi, current.hi));
prev = Interval;
} else {
prev = current;
}
removeIfExist(result, prev);
result.add(prev);
}
return result;
}
private static void removeIfExist(ArrayList<Interval> result, Interval prev) {
if (result.size() > 0) {
Interval existing = result.get(result.size() - 1);
if (existing.lo == prev.lo) {
result.remove(result.size() - 1);
}
}
}
public static void main(String[] args) {
ArrayList<Interval> list = new ArrayList<Interval>();
System.out.println("--------------------------------------------------------------------------------");
list.add(new Interval(30, 50));
list.add(new Interval(20, 40));
list.add(new Interval(75, 90));
list.add(new Interval(1, 10));
list.add(new Interval(95, 100));
list.add(new Interval(65, 80));
list.add(new Interval(55, 65));
System.out.println("Input: " + list);
System.out.println("merged Interval: " + merge(list));
System.out.println("--------------------------------------------------------------------------------");
}
}