区间合并算法

需求:给定多个连续的区间,将区间进行合并,输出一个或多个没有交集的连续区间。

支持泛型,可以用数值或者字符串表示区间(实际上是Comparable接口)。

环境:jdk1.8

package cn.howso.deeplan.psi.vague.utils.interval;

import net.sf.json.JSONObject;

/**
 * 区间
 * */
public class Interval<T extends Comparable<T>>{
    private T begin;
    private T end;
    public static <E extends Comparable<E>> Interval<E> of(E begin,E end){
        Interval<E> ts = new Interval<>();
        if(begin.compareTo(end)>0){
            throw new RuntimeException("begin should not bigger than end");
        }
        ts.begin = begin;
        ts.end = end;
        return ts;
    }
    
    public T getBegin() {
        return begin;
    }
    
    public T getEnd() {
        return end;
    }
    @Override
    public String toString() {
        return JSONObject.fromObject(this).toString();
    }
}


package cn.howso.deeplan.psi.vague.utils.interval;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import org.springframework.util.Assert;
/*区间合并器*/
public class Merger {
    public <E extends Comparable<E>> List<Interval<E>> merge(List<Interval<E>> intervals) {
        Assert.isTrue(!intervals.isEmpty(), "interval list size is 0");
        intervals.sort((o1, o2) -> o2.getBegin().compareTo(o1.getBegin()));
        Stack<Interval<E>> stack = new Stack<>();
        List<Interval<E>> result = new ArrayList<>();
        intervals.forEach(item -> stack.push(item));
        while (stack.size() > 1) {
            Interval<E> i1 = stack.pop();
            Interval<E> i2 = stack.pop();
            List<Interval<E>> mergedList = mergeSingle(i1, i2);
            if (mergedList.size() == 2) {
                result.add(mergedList.get(0));
            }
            stack.push(mergedList.get(mergedList.size()-1));
        }
        result.add(stack.pop());
        return result;
    }


    private <E extends Comparable<E>> List<Interval<E>> mergeSingle(Interval<E> first, Interval<E> second) {
        Assert.isTrue(first.getBegin().compareTo(second.getBegin())<=0,"first interval's begin should less than second's");
        
        List<Interval<E>> result = new ArrayList<>(2);
        if(first.getEnd().compareTo(second.getBegin())<0){
            result.add(first);
            result.add(second);
        }else{
            E end;
            if(first.getEnd().compareTo(second.getEnd())>=0){
                end = first.getEnd();
            }else{
                end = second.getEnd();
            }
            result.add(Interval.of(first.getBegin(), end));
        }
        return result;
    }
}

单元测试

package cn.howso.deeplan.psi.vague.utils.interval;


import java.util.ArrayList;
import java.util.List;


import org.junit.Test;


import junit.framework.Assert;


public class MergerTest {
    @Test
    public void test(){
        List<Interval<Long>> intervals = new ArrayList<>();
        intervals.add(Interval.of(1L, 5L));
        intervals.add(Interval.of(2L, 3L));
        intervals.add(Interval.of(8L, 10L));
        intervals.add(Interval.of(4L, 6L));
        intervals.add(Interval.of(7L, 8L));
        Merger merger = new Merger();
        List<Interval<Long>> newIntervals = merger.merge(intervals);
        System.out.println(newIntervals);
        Assert.assertTrue(newIntervals.size()==2);
    }
}


猜你喜欢

转载自blog.csdn.net/zhoujiaping123/article/details/73895244
今日推荐