在Java中将Sorted Set转换为Range语句

时间:2014-04-14 21:01:26

标签: java

我有一个排序集,其元素为[1,2,3,4,5,10,12,45,46,47,50]

我需要将此集转换为Range语句,其中连续元素以min .. max表示。 这里确切的是预期的产出。

1..5 / 10/12 / 45..47 / 50

由于1至5是连续的,因此它们由1..5表示,因此表示为45..47

10,12等等是不连续的,因此它们被Union分开。

任何人都可以帮我解决任何内置方法或高效算法吗? 目前我使用的是迭代器,但是卡在中间。

String SetToRange(Set<Integer> S, long maxint)
    {
        Integer min,max;
        StringBuilder Range=new StringBuilder("");
        Iterator I=S.iterator();
        switch(S.size())
        {
            case 0: Range.append("0.."+maxint);
                    System.out.println("RangeStatement for Set Size 0 is"+Range);
                    return Range.toString();
            case 1: min=max=(Integer)I.next();
                    Range.append(min);
                    System.out.println("RangeStatement="+Range);    
                    return Range.toString();
            case 2: min=(Integer)I.next();
                    max=(Integer)I.next();
                    if(max==min+1)
                    {
                        Range.append(min.toString()+".."+max.toString());
                    }
                    else
                    {
                        Range.append(min+"\\/"+max);
                    }
                    System.out.println("Range Statement:-"+Range);
                    return Range.toString();
        }
         System.out.println("The Set has more than Two Elements="+S.size());
         min=(Integer)I.next();
         max=(Integer)I.next();
         //Working out logic for this Part using Two Iterators
         return Range.toString();

    }

谢谢,

3 个答案:

答案 0 :(得分:2)

您可以在O(n)时间执行此操作。此示例使用面向对象方法显示它。

首先创建一个Range类。

class Range {
    int from;
    int to;

    public Range setFrom(int from) {
        this.from = from;
        return this;
    }

    public Range setTo(int to) {
        this.to = to;
        return this;
    }

    @Override
    public String toString() {
        return "Range [from=" + from + ", to=" + to + "]";
    }   
}

现在只需迭代数组并比较相邻的元素。

如果它们的差异优于1,则它们不是连续的,因此您设置上一个范围的上限,将其添加到列表中,然后创建一个设置其下限的新值。

public class Test { 

    public static void main(String[] args){
        Set<Integer> setOfIntegers = new LinkedHashSet<>(Arrays.asList(1,2,3,4,5,10,12,45,46,47,49));
        System.out.println(getRanges(setOfIntegers));
    }

    public static List<Range> getRanges(Set<Integer> s){
        List<Range> list = new ArrayList<>();
        Integer[] setOfIntegers = s.toArray(new Integer[s.size()]);

        Range r = new Range().setFrom(setOfIntegers[0]);
        for(int i = 1; i < setOfIntegers.length; i++){
             if(setOfIntegers[i] - setOfIntegers[i-1] != 1){
                 list.add(r.setTo(setOfIntegers[i-1]));
                 r = new Range().setFrom(setOfIntegers[i]);
             }
        }
        list.add(r.setTo(setOfIntegers[setOfIntegers.length-1]));

        return list;
    }
}

一些输出:

[1,2,3,4,5,10,12,45,46,47,49] => [Range [from=1, to=5], Range [from=10, to=10], Range [from=12, to=12], Range [from=45, to=47], Range [from=49, to=49]]

[4,7,8,9,15,20,21] => [Range [from=4, to=4], Range [from=7, to=9], Range [from=15, to=15], Range [from=20, to=21]]

[-17,-6,-4,-3,-2,0,1,4] => [Range [from=-17, to=-17], Range [from=-6, to=-6], Range [from=-4, to=-2], Range [from=0, to=1], Range [from=4, to=4]]

请注意,我没有检查该集合是否没有元素等。但是您有一般性的想法,根据您的需要修改它应该不难。

答案 1 :(得分:0)

所以,你的基本功能是:

f(List<int>) => List<List<int>>

这样输出的内部列表保证只有连续的数字,并且没有两个这样的列表具有连续的数字。所以你的算法看起来像:

sort(List<int> input)
  List<List<int>> output = new List<List<Int>>();
  while (input.hasElements())
    output.append( getNextConsecutive(input))//NOTE: getNextConsecutive modifies input!
  return output

getNextConsecutive(List<int> input)
  List<int> output = new List<int>();
  while (input.next() == ouput.last() + 1) {
    output.append(input.pop);//note: removes from input
  }
  return output

请注意,此算法省略了输出,因为它是一个单独的问题,应该由另一个函数自然处理:

printLists(List<List<int>> input)
  for each List in input, sublist
    if sublist.length > 1
      print sublist.first
      print ".."
      print sublist.last
    if sublist.length == 1
      print sublist.first
  print "/"

答案 2 :(得分:0)

以下是您问题的解决方案。

import java.util.Set;
import java.util.TreeSet;

public class SetRange {

    public static String getRangeString(Set<Integer> rangeSet) {

        StringBuffer strBuilder = new StringBuffer();
        Integer lastValue = null;
        boolean contineous = false;
        for (Integer value : rangeSet) {
            if (lastValue != null && lastValue + 1 == value.intValue()) {
                contineous = true;
            } else {
                if (contineous) {
                    strBuilder.deleteCharAt(strBuilder.length() - 1);
                    strBuilder.append(".." + lastValue + "/" + value + "/");
                } else {
                    strBuilder.append(value + "/");
                }
                contineous = false;

            }
            lastValue = value;
        }
        String answer = strBuilder.toString();
        if (answer.length() > 0) {
            answer = answer.substring(0, answer.length() - 1);
        }
        return answer;
    }

    public static void main(String[] args) {
        Set<Integer> rangeSet = new TreeSet<Integer>();
        rangeSet.add(1);
        rangeSet.add(2);
        rangeSet.add(3);
        rangeSet.add(4);
        rangeSet.add(5);
        rangeSet.add(10);
        rangeSet.add(12);
        rangeSet.add(45);
        rangeSet.add(46);
        rangeSet.add(47);
        rangeSet.add(50);

        String answer = getRangeString(rangeSet);
        System.out.println(answer);
    }
}