2

最小値と最大値で構成される Range オブジェクトがあります。したがって、次のような範囲が存在する可能性があります。

[1, 5]
[6, 12]
[13, 14]

これが私の質問です。によって与えられる範囲のリストがあるとします。

ArrayList<Range> ranges;

範囲が重複しないように修正する必要があります。つまり、次の 2 つの機能があります。

public void addRange(Range r);

public void removeRange(Range r);

ranges各メソッドの後、 ArrayList は常に最小値でソートされると想定できます。rangesArrayList には常に の初期範囲が含まれていることに注意してください[1, 100]ranges前後の例を次に示します。

ranges = {[1,5], [6,12], [13,14]}
addRange([7, 15])
ranges = {[1,5], [6,15]}

ranges = {[1,12], [18,29], [34,89]}
addRange([16,17])
ranges = {{[1,12], [16,17], [18,29], [34,89]}

ranges = {[16,35]}
removeRange([19,54])
ranges = {[16,19]}

これら2つの関数をどのように書くことができますか?

4

1 に答える 1

2

これはうまくいくはずです。これは O(n) であるため、より高速な検索/並べ替えアルゴリズムに置き換えることができます。

DistinctRangeList.java

package range;

import java.util.LinkedList;

public class DistinctRangeList {

    private LinkedList<Range> linkedList;

    public DistinctRangeList() {
        linkedList = new LinkedList<Range>();
    }

    public void add(Range newRange) {
        for (int i = 0; i < linkedList.size(); i++) {
            Range range = linkedList.get(i);
            if (range.overlaps(newRange)) {
                return;
            } else if (newRange.min < range.min) {
                linkedList.add(i, newRange);
                return;
            } else {
                continue;
            }
        }
        linkedList.addLast(newRange);
    }

    public void remove(Range remove) {
        for (int i = 0; i < linkedList.size(); i++) {
            Range range = linkedList.get(i);
            if (range.equals(remove)) {
                linkedList.remove(range);   
            }
        }
    }

    public String toString() {
        String s = "";
        for (Range r : linkedList) {
            s += String.format("[%d, %d] ", r.min, r.max);
        }
        return s;
    }

    public static void main(String[] args) {
        DistinctRangeList lst = new DistinctRangeList();
        lst.add(new Range(3, 6)); // should add
        lst.add(new Range(3, 5)); // should not add
        lst.add(new Range(7, 8)); // should add
        lst.add(new Range(10, 15)); // should add
        lst.remove(new Range(10, 15)); 
        lst.add(new Range(10, 12)); // should add
        lst.add(new Range(1, 2)); // should add to the beginning
        System.out.println(lst);
    }
}

範囲.java

package range;

public class Range {
    public int min, max;

    public Range(int min, int max) {
        this.min = min; this.max = max;
    }

    public boolean equals(Range other) {
        return this.min == other.min && this.max == other.max;
    }

    public boolean overlaps(Range other) {
        return (min <= other.min && other.min <= max) ||
               (min <= other.max && other.max <= max);
    }
}



わかりました、これはあなたが望んでいたものだと思います。(それは興味深い問題だったので、私はそれを進めました。)

RangeSet.java

package range;

import java.util.LinkedList;

public class RangeSet {

    private LinkedList<Range> linkedList;

    public RangeSet() {
        linkedList = new LinkedList<Range>();
    }

    public void add(Range range) {

        System.out.println("Adding " + range + " ...");

        if (linkedList.contains(range)) {
            return;
        }

        // First place the new range
        boolean done = false;
        for (int i = 0; i < linkedList.size() && !done; i++) {
            Range current = linkedList.get(i);
            if (range.min < current.min) {
                linkedList.add(i, range);
                done = true;
            }
        }
        if (!done) {
            linkedList.addLast(range);
        }

        // Now, do the necessary merges
        for (int i = 0; i < linkedList.size() - 1; i++) {
            Range current = linkedList.get(i);
            Range next = linkedList.get(i + 1);
            if (current.overlaps(next)) {
                current.extendBy(next);
                linkedList.remove(i + 1);
            }
        }

        System.out.println(this);
    }

    public void remove(Range remove) {

        System.out.println("Removing " + remove + " ...");

        for (int i = 0; i < linkedList.size(); i++) {

            Range current = linkedList.get(i);

            if (!current.overlaps(remove)) { // no overlap

                continue;

            } else if (remove.min <= current.min && remove.max >= current.max) { // the range to remove contains the current node

                linkedList.remove(i);

            } else if (remove.min < current.min) { // the range to remove intersects the current node from the left end

                current.min = remove.max;

            } else if (remove.max > current.max) { // [...] from the right end

                current.max = remove.min;

            } else { // the range to remove is contained within the current node, splitting it in two

                Range start = new Range(current.min, remove.min);

                Range end = new Range(remove.max, current.max);

                linkedList.remove(i);

                linkedList.add(i, start);

                linkedList.add(i + 1, end);
            }
        }

        System.out.println(this);
    }

    public String toString() {
        String s = "";
        for (Range r : linkedList) {
            s += r.toString() + " ";
        }
        return s;
    }

    public static void main(String[] args) {
        RangeSet set = new RangeSet();
        set.add(new Range(3, 6));
        set.add(new Range(1, 2));
        set.add(new Range(4, 10));
        set.add(new Range(50, 100));
        set.remove(new Range(9, 90));
        System.out.println("Final result:\n" + set);
    }
}

範囲.java

package range;

public class Range {
    public int min, max;

    public Range(int min, int max) {
        this.min = min; this.max = max;
    }

    public boolean equals(Range other) {
        return this.min == other.min && this.max == other.max;
    }

    public boolean overlaps(Range other) {
        return (min <= other.min && other.min <= max) ||
               (min <= other.max && other.max <= max);
    }

    public void extendBy(Range other) {
        if (other.min < this.min) {
            this.min = other.min;
        }
        if (other.max > this.max) {
            this.max = other.max;
        }
    }

    public String toString() {
        return String.format("[%d, %d]", min, max);
    }
}
于 2012-12-29T22:07:56.063 に答える