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

后端 未结 16 3249
我在风中等你
我在风中等你 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:31

    If the array is sorted, as in your example, I would define buckets containing a min and a max.

    Initialize: Create a bucket with a min and a max equal to the first value.

    Loop: Compare each value with the max of the current bucket. If it is equal to or 1 more than the current max, update the max. If it is more than 1 greater than the max, save the bucket to a list of buckets and start a new bucket.

    At the end you will have a set of buckets with a min and a max in each. If the min is the same as the max, print a single number (ie: in your example, the first bucket would have a min and a max of 1). If they are different, print as a range.

    Example implementation in lisp:

    CL-USER> (defun print-ranges (integer-list)
               (let ((sorted-list (sort integer-list #'<)))
                 (loop with buckets = ()
                       with current-bucket
                       for int in sorted-list
                         initially (setf current-bucket (cons (first sorted-list) (first sorted-list)))
                       do (cond ((= int (cdr current-bucket))) ; do nothing, this number is already in range
                                ((= (1- int) (cdr current-bucket)) ; number is 1 higher--update bucket's max
                                 (setf (cdr current-bucket) int))
                                (t
                                 (push current-bucket buckets)
                                 (setf current-bucket (cons int int)))) ; set up a new bucket
                       finally (push current-bucket buckets)
                               (loop for firstp = t then nil
                                     for bucket in (nreverse buckets) do
                                       (cond ((= (car bucket) (cdr bucket))
                                              (format t "~:[,~;~]~D" firstp (car bucket)))
                                             (t
                                              (format t "~:[,~;~]~D-~D" firstp (car bucket) (cdr bucket))))))))
    PRINT-RANGES
    CL-USER> (print-ranges (list 1 3 4 5 6 8 11 12 14 15 16))
    1,3-6,8,11-12,14-16
    NIL
    CL-USER> 
    

    Basically you end up with a list of things, where each thing has (lowest-in-bucket, highest-in-bucket). Those are your ranges.

    If the list is not already sorted, sort it first.

提交回复
热议问题