我们让int[] A = new int[1000]
和int[] subA = new int [300]
subA \in A
(subA
是A
的子集)。如何在Java中以最快的方式查找数组A \ subA
?给定的数组A
和subA
都已排序。
编辑:抱歉,忘记提到数组包含不同的元素,只是它们包含其他结构的矩形,如矩阵行。
我正在考虑这个解决方案:
// 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;
}
目前正在测试这种方法。答案准备好后我会回来的。
答案 0 :(得分: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];
}
答案 1 :(得分: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。我没有检查所有的索引位置和计算,但是你明白了。
答案 2 :(得分:0)
既然你说两个数组都是排序的,这听起来像是“我希望你遍历两个数组并从sub中删除A部分之间的部分”对我来说有点做作业。
所以让我们尝试起草
意味着我们可以做类似的事情......
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;
答案 3 :(得分:0)
最快最有效的方法是使A \ SubA成为A上的视图,即不保留对元素的自己引用,但由A和SubA支持。这类似于difference from 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;
}
};
}
}