moyen efficace de supprimer des éléments de la liste des gammes d'une plus grande gamme

idée de génie :

Je cherche un moyen efficace de supprimer une liste de plages d'une plus grande gamme. La liste des plages sera contenu avec la plus grande gamme

par exemple:

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

J'ai une mise en œuvre ci-dessous, mais il est O (n2) et prend plus d'espace de taille 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:

Reportez-vous à idée @Bohemian en changeant votre méthode de « ajouter tout élément puis retirez par gamme » à « élément rapporté de supprimer plage »

  1. Trier les rangesToBeRemoved (par range.start)
  2. Boucle sur l'élément de gamme et ajouter qui couvre pas par des plages
  3. Ajouter tout élément après la fin de la dernière plage

    // 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);
        }
    }
    

Après le tri de la rangesToBeRemoved, la relation entre les deux gammes sont

  1. Complètement dans la gamme (par exemple (2,7) et (4,6))
  2. En partie dans la gamme (par exemple (2,7) et (6,8))
  3. Pas dans la gamme (par exemple, (2,3) et (6,8) || (2,3) et (4,8))

Pour le cas 1, ignorer la deuxième plage. Pour le cas 2, mettez à jour la frontière à la fin de la deuxième plage. Pour le cas 3, ajouter l'écart à la liste des éléments et mettre à jour la frontière à la fin de la deuxième plage.

Le code ci-dessus tente de comparer plage virtuelle (outer.start-1, borderElementIndex) et toutes les gammes de rangesToBeRemoved (triée)

Réutiliser votre exemple: {(2,7), (4,6), (6,8)}.

  • Tout d'abord, comparer (-1, -1) (2,7) et cas de succès 3, ajouter l'écart [0,1] en jeu de résultats et changer le borderElementIndex à 7.
  • Ensuite, comparez (-1,7) avec (4,6) et cas de succès 1, l'ignorer.
  • Ensuite, comparez (-1,7) avec (6,8) et cas de succès 2, changer le borderElementIndex à 8.
  • Greffer écart restant [9,10] dans le jeu de résultats.

Pour réduire davantage l'utilisation de l'espace, vous pouvez utiliser le même état d'idée en solution @Danny_ds pour stocker la gamme d'éléments au lieu d'éléments individuels.

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=186617&siteId=1
conseillé
Classement