5

让我们有int[] A = new int[1000]andint[] subA = new int [300]这样subA \in A(subAA) 的子集。A \ subA如何在 Java 中以最快的方式找到数组?给定数组AsubA排序。

编辑:对不起,忘了提到数组包含不同的元素,只是它们包含其他结构的索引,如矩阵行。

我正在考虑这个解决方案:

// supp is short for supplement
int[] supp = new int[A.length - subA.length];
int j = A[0], c = 0;
for (int i = 0; i < subA.lengh; i++) {
    // elegantly can be: while (j < subA[i]) supp[c++] = j++;
    while (j < subA[i]) {
        supp[c] = j;
        c++; j++;
    }
    j = subA[i] + 1;
}

目前正在测试这种方法。准备好答案后我会回来的。

4

4 回答 4

4

尝试这样的事情:

// A index
int ai = 0;
// subA index
int sai = 0;
// result array
int[] result = new int[A.length - subA.length];
// index in result array
int resi = 0;

while ai < A.length && sai < subA.length;
    // same elements - ignore
    if (A[ai] == subA[sai]) {
        ai++;
        sai++;
    // found an element in A that does not exist in subA
    } else {
        // Store element
        result[resi] = A[ai];
        resi++;
        ai++;
    }
}

// Store elements that are left in A
for (;ai < A.length; ai++, resi++) {
    result[resi] = A[ai];
}
于 2012-11-02T11:05:31.620 回答
1

如果你说元素是有序的并且都是不同的,那么你只需要在A中找到subA的第一个元素的索引,然后用System.arrayCopy()最有效的方式复制数据:

    int index = Arrays.binarySearch(A, subA[0]);

    int[] diff = new int[A.length - subA.length];

    System.arraycopy(A, 0, diff, 0, index);
    System.arraycopy(A, index+subA.length, diff, index, A.length-index-subA.length);

PS。我没有检查所有的索引位置和计算,但你明白了。

于 2012-11-02T12:38:37.673 回答
0

既然您说两个数组都已排序,这听起来像是“我希望您遍历两个数组并从 subA 成员之间的 A 中删除部分”对我来说有点像家庭作业。

所以让我们试着草拟一下

  • 数组 A 按 1000 个成员排序
  • subA 按 300 个成员排序
  • arrayA 包含所有 subA 的元素

这意味着我们可以做类似...

public ArrayList findDifferences(int[] arrayA, int[] subA)
{
    ArrayList retVal = new ArrayList();
    for(int i = 0; i < arrayA.size; i++)
    {  
        if(arrayA[i] < subA[index]
            retVal.add(arrayA[i]);
        else if(arrayA[i] == subA[index])
            index++;
    }
    return retVal;
}

我想说的是,你可以以某种方式计算要复制的范围,但我猜它最终会是这样。

然后还有这个

 List a = new List();
 a.addAll(arrayA);
 List b = new List();
 b.addAll(subA);
 a.removeAll(b);
 return a;
于 2012-11-02T11:11:01.193 回答
0

最快和最有效的方法是使 A\SubA 成为 A 上的视图,即不持有对元素的自己的引用,而是由 A 和 SubA 支持。这类似于与Guava Sets 的区别

当然,必须考虑创建该视图后对 A 和 SubA 的更改,这可能是优点或缺点,具体取决于您的情况。

任意列表的示例性实现(即在您的情况下,使用new ImmutableSubarrayList<E>(Arrays.asList(A),Arrays.asList(SubA))

import java.util.AbstractSequentialList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;


public class ImmutableSubarrayList<E extends Comparable<E>> extends AbstractSequentialList<E>{

    final List<E> a, subA;
    final int size;

    public ImmutableSubarrayList(List<E> aParam, List<E> subAParam){
        super();
        a = aParam;
        subA = subAParam;
        assert a.containsAll(subA) : "second list may only contain elements from first list";

        // Iterate over a, because a.size()-subA.size() may not be correct if a contains equal elements. 
        int sizeTemp = 0;
        for (E element : a){    
            if (!subA.contains(element)){
                sizeTemp++;
            }
        }
        size = sizeTemp;
    }

    public int size() {
        return size;
    }

    public ListIterator<E> listIterator(final int firstIndex) {
        //create a ListIterator that parallely 
        // iterates over a and subA, only returning the elements in a that are not in subA
        assert (firstIndex >=0 && firstIndex <= ImmutableSubarrayList.this.size()) : "parameter was "
                           +firstIndex+" but should be betwen 0 and "+ImmutableSubarrayList.this.size();
        return new ListIterator<E>() {

            private final ListIterator<E> aIter = a.listIterator();
            private final ListIterator<E> subAIter = subA.listIterator();
            private int nextIndex = 0;

            {
                for (int lv = 0; lv < firstIndex; lv++ ){
                    next();
                }
            }

            @Override
            public boolean hasNext() {
                return nextIndex < size;
            }

            @Override
            public void add(E arg0) {
                throw new UnsupportedOperationException("The list being iteratred over is immutable");
            }

            @Override
            public boolean hasPrevious() {
                return nextIndex > 0;
            }

            @Override
            public int nextIndex() {
                return nextIndex;
            }

            @Override
            public E next() {
                if (!hasNext()){
                    throw new NoSuchElementException();
                }
                nextIndex++;
                return findNextElement();
            }

            @Override
            public E previous() {
                if (!hasPrevious()){
                    throw new NoSuchElementException();
                }
                nextIndex--;
                return findPreviousElement();
            }

            @Override
            public int previousIndex() {
                return nextIndex-1;
            }

            @Override
            public void set(E arg0) {
                throw new UnsupportedOperationException("The list being iteratred over is immutable");
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("The list being iteratred over is immutable");          
            }

            private E findNextElement() {
                E potentialNextElement = aIter.next();
                while (subAIter.hasNext()){
                    E nextElementToBeAvoided = subAIter.next();
                    subAIter.previous();
                    assert (potentialNextElement.compareTo(nextElementToBeAvoided) > 0) : 
                        "nextElementToBeAvoided should not be smaller than potentialNextElement";
                    while (potentialNextElement.compareTo(nextElementToBeAvoided) == 0){
                        potentialNextElement = aIter.next();
                    }
                    subAIter.next();
                }
                return potentialNextElement;
            }

            //in lack of lambdas: clone of findNextElement()
            private E findPreviousElement() {
                E potentialPreviousElement = aIter.previous();
                while (subAIter.hasPrevious()){
                    E previousElementToBeAvoided = subAIter.previous();
                    subAIter.previous();
                    assert (potentialPreviousElement.compareTo(previousElementToBeAvoided) < 0) : 
                        "previousElementToBeAvoided should not be greater than potentialPreviousElement";
                    while (potentialPreviousElement.compareTo(previousElementToBeAvoided) == 0){
                        potentialPreviousElement = aIter.previous();
                    }
                    subAIter.previous();
                }
                return potentialPreviousElement;
            }
        };
    }
}
于 2012-11-02T11:11:02.907 回答