How would you display an array of integers as a set of ranges? (algorithm)

后端 未结 16 2888
我在风中等你
我在风中等你 2021-02-15 18:04

Given an array of integers, what is the simplest way to iterate over it and figure out all the ranges it covers? for example, for an array such as:

$numbers = ar         


        
相关标签:
16条回答
  • 2021-02-15 18:07

    My solution in Java 1.5 would be:

    public static List<String> getRanges(int... in) {
        List<String> result = new ArrayList<String>();
        int last = -1;
        for (int i : in) {
            if (i != (last + 1)) {
                if (!result.isEmpty()) {
                    addRange(result, last);
                }
                result.add(String.valueOf(i));
            } 
            last = i;
        }
        addRange(result, last);
        return result;
    }
    
    private static void addRange(List<String> result, int last) {
        int lastPosition = result.size() - 1;
        String lastResult = result.get(lastPosition);
        if (!lastResult.equals(String.valueOf(last))) {
            result.set(lastPosition, lastResult + "-" + last);
        }
    }
    
    public static void main(String[] args) {
        List<String> ranges = getRanges(1, 3, 4, 5, 6, 8, 11, 12, 14, 15, 16);
        System.out.println(ranges);
    }
    

    which outputs:

    [1, 3-6, 8, 11-12, 14-16]
    

    Greetz, GHad

    0 讨论(0)
  • 2021-02-15 18:07
    module Main where
    
    ranges :: [Int] -> [[Int]]
    ranges [] = []
    ranges list@(x:xs) = let adj = adjacent list in
                 let len = length adj in
                     if length adj == 1
                    then [[x]] ++ ranges xs
                    else [[x,(last adj)]] ++ ranges (drop ((length adj) - 1) xs)
        where adjacent [] = []
              adjacent (x:xs) = if (xs /= []) && (x + 1) == head xs
                 then [x] ++ adjacent (xs)
                 else [x]
    
    main = do putStrLn $ show $ ranges [1,2,3,4,5,6,8,11,12,14,15,16]
    
    -- Output: [[1,6],[8],[11,12],[14,16]]
    

    Here's my best shot in Haskell.

    0 讨论(0)
  • 2021-02-15 18:10

    Create a simple range type which contains start / end of range values. Add a constructor which takes only one value and sets start = end = value. Maintain a stack of range objects, work your way through a sorted copy of the array, extend the top range or add a new range as appropriate. More specifically, when the value in the array is 1 + the end value for the range object on the to of the stack, increment the end value for that range, when it's not, push a new range (with start = end = value at index in array) onto the stack.

    0 讨论(0)
  • 2021-02-15 18:15
    startRange = array[0];    
    for(i=0;i<array.length;i++)
    {
       if (array[i + 1] - array[i] > 1)
       {
         endRange = array[i];
         pushRangeOntoArray(startRange,endRange);
         i++;
         startRange = array[i]
         // need to check for end of array here
       }
    }
    
    0 讨论(0)
  • 2021-02-15 18:16

    Assuming the list is ordered you could start at the end and keep subtracting the next one down. While the difference is 1, you're in a range. When it's not, you start a new range.

    i.e

    16-15 = 1

    15-14 = 1

    14-12 = 2, the range is 16-14 - start a new range.

    0 讨论(0)
  • 2021-02-15 18:17

    If the array is sorted in ascending order, then the problem is easy. Define a Range structure or class, which has a beginning and an end. Then go through the array. If the current element is one more than the previous, update Range.end, otherwise create a new range with this element as Range.begin. Store the ranges to a dynamic array or a linked list. Or just print them out as you go.

    If the array may not be sorted, then sort it first.

    0 讨论(0)
提交回复
热议问题