forma eficaz de eliminar elementos de lista de rangos de una gama más grande

lluvia de ideas:

Busco una forma eficaz para eliminar una lista de rangos entre una gama más grande. La lista de rangos estará contenida con la gama más grande

p.ej:

Bigger range: (0,10) 
List of Ranges:  [(2,7),(4,6),(6,8)]
expected result: {0,1,9,10}

Tengo una implementación más adelante, pero es O (n2) y tiene espacio adicional de tamaño O (n);

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/***
* input -> (0,10) and {(2,7),(4,6),{6,8}}
 * output -> {0,1,9,10}
 ***/
public class RemoveRanges {

    public static class Range {
        int start;
        int end;

        public Range(int x, int y){
            this.start = x;
            this.end = y;

        }
    }

    public static void main(String[] args) {

        Range outer = new Range(0,10);
        Range r1 = new Range(2,7);
        Range r2 = new Range(4,6);
        Range r3 = new Range(6,8);
        List<Range> rangesToBeRemoved = new ArrayList<>();
        rangesToBeRemoved.add(r1);
        rangesToBeRemoved.add(r2);
        rangesToBeRemoved.add(r3);

        System.out.println(removeRanges(outer, rangesToBeRemoved));

    }

    public static Set<Integer> removeRanges(Range outer, List<Range> rangesToBeRemoved ) {

        Set<Integer> outerElements = new HashSet<>();

        for (int i = outer.start; i<=outer.end;i++ ){
            outerElements.add(i);
        }

        for (Range range : rangesToBeRemoved) {
            for (int j = range.start; j<=range.end; j++) {
                outerElements.remove(j);
            }
        }
        return outerElements;
    }
}
hk6279:

Consulte la idea @Bohemian cambiando su método de "poner todos los elementos a continuación, eliminar por rango" a "elemento de complemento fuera de rango remove"

  1. Ordenar la rangesToBeRemoved (por range.start)
  2. Lazo sobre el elemento de rango y añadir que no se cubre por cadenas
  3. Añadir todos los elementos después del final de la última gama

    // assume rangesToBeRemoved has been sorted
    public static Set<Integer> addElementbyRemovedRanges(Range outer, List<Range> rangesToBeRemoved ) {
    
        Set<Integer> outerElements = new HashSet<Integer>();
    
        // this variable record the last element that has handled and act like a borderline
        int borderElementIndex = outer.start-1;
        for (Range range : rangesToBeRemoved) {
            if (range.end <= borderElementIndex ) {
                // omit this range as it has been cover by previous range(s)
                continue;
            }
    
            // add range if there is gap between range
            if (range.start > borderElementIndex ) {
                addElements(outerElements, borderElementIndex + 1, range.start - 1);
            }
    
            // update borderline
            borderElementIndex = range.end;
        }
        // Add all element after the last range's end
        addElements(outerElements, borderElementIndex + 1, outer.end);
    
        return outerElements;
    }
    
    public static void addElements(Set<Integer> outerElements, int start, int end) {
        if (start > end) {
            return;
        }
        for (int i=start; i<=end; i++){
            outerElements.add(i);
        }
    }
    

Después de la clasificación del rangesToBeRemoved, relación entre dos intervalos se

  1. Completamente en el rango (por ejemplo, (2,7) y (4,6))
  2. Parcialmente en el rango (por ejemplo, (2,7) y (6,8))
  3. Fuera del rango (por ejemplo, (2,3) y (6,8) || (2,3) y (4,8))

Para el caso 1, ignorar el segundo rango. Para el caso 2, actualice la frontera a finales de segundo rango. Para el caso 3, añadir la brecha a la lista de elementos y actualizar la frontera a finales de segundo rango.

El código anterior está tratando de comparar rango virtual (outer.start-1, borderElementIndex) y todos los intervalos en rangesToBeRemoved (ordenadas)

Reutilizar su ejemplo: {(2,7), (4,6), (6,8)}.

  • En primer lugar, comparar (-1, -1) con (2,7) y el caso hit 3, añadir la brecha [0,1] en consecuencia establecer y cambiar la borderElementIndex a 7.
  • A continuación, comparar (-1,7) con (4,6) y la caja 1 hit, ignorarlo.
  • A continuación, comparar (-1,7) con (6,8) y la caja golpe 2, cambie el borderElementIndex a 8.
  • Finalmente, append restante brecha [9,10] en conjunto de resultados.

Para reducir aún más el uso del espacio, se puede usar el mismo estado idea en solución @Danny_ds para almacenar el rango de elemento en lugar de elementos individuales.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=186619&siteId=1
Recomendado
Clasificación