我尝试找到解决此问题的方法: 我有两个整数A和B(A和B可以有不同的尺寸)。我必须在这两个数组中找到共同的元素。我有另一个条件:公共元素之间的最大距离是k。 所以,这是我的解决方案。我认为是正确的:
for (int i = 0; i<A.length; i++){
for (int j=jlimit; (j<B.length) && (j <= ks); j++){
if(A[i]==B[j]){
System.out.println(B[j]);
jlimit = j;
ks = j+k;
}//end if
}
}
有没有办法做出更好的解决方案?有什么建议?提前谢谢!
答案 0 :(得分:5)
根据您的解释,我认为最直接的方法是读取数组A,将所有元素放在Set
(setA)中,对B(setB)执行相同操作,并使用retainAll
方法找到两个集合的交集(属于这两个集合的项目)。
您将看到k distance
根本没有被使用,但我认为无法使用导致代码更快或更可维护的条件。我提倡的解决方案在没有强制执行该条件的情况下工作,因此当条件为真时(即称为“削弱先决条件”),它也可以工作
答案 1 :(得分:5)
实施二进制搜索和快速排序!
这将导致大量的代码....但最快的结果。
您可以使用类似的快速排序对较大数组的元素进行排序,这将导致O(nlogn)。
然后遍历每个值的较小数组,并对另一个数组中的特定元素进行二进制搜索。在二进制搜索中为距离添加一些逻辑。
我认为你可以将复杂性降低到O(nlogn)。最坏情况O(n ^ 2)
伪代码。
larger array equals a
other array equals b
sort a
iterate through b
binary search b at iterated index
// I would throw (last index - index) logic in binary search
// to exit out of that even faster by returning "NOT FOUND" as soon as that is hit.
if found && (last index - index) is less than or equal
store last index
print value
这是解决问题的最快方法。
答案 2 :(得分:2)
虽然这可能是作弊,但由于它使用HashSet
s,因此对于此算法的Java实现来说非常好。如果您需要算法的伪代码,请不要再阅读。
JavaDoc中的源代码和作者。干杯。
/**
* @author Crunchify.com
*/
public class CrunchifyIntersection {
public static void main(String[] args) {
Integer[ ] arrayOne = { 1, 4, 5, 2, 7, 3, 9 };
Integer[ ] arrayTwo = { 5, 2, 4, 9, 5 };
Integer[ ] common = iCrunchIntersection.findCommon( arrayOne, arrayTwo );
System.out.print( "Common Elements Between Two Arrays: " );
for( Integer entry : common ) {
System.out.print( entry + " " );
}
}
public static Integer[ ] findCommon( Integer[ ] arrayOne, Integer[ ] arrayTwo ) {
Integer[ ] arrayToHash;
Integer[ ] arrayToSearch;
if( arrayOne.length < arrayTwo.length ) {
arrayToHash = arrayOne;
arrayToSearch = arrayTwo;
} else {
arrayToHash = arrayTwo;
arrayToSearch = arrayOne;
}
HashSet<Integer> intersection = new HashSet<Integer>( );
HashSet<Integer> hashedArray = new HashSet<Integer>( );
for( Integer entry : arrayToHash ) {
hashedArray.add( entry );
}
for( Integer entry : arrayToSearch ) {
if( hashedArray.contains( entry ) ) {
intersection.add( entry );
}
}
return intersection.toArray( new Integer[ 0 ] );
}
}
答案 3 :(得分:2)
您的实施大致为O(A.length * 2k)。
如果您希望保持“不超过k”逻辑,这似乎就是您要做的最好的事情,因为排除了排序和使用集即可。我会改变一点,使你的代码更容易理解。
首先,我会确保您迭代两个数组中较小的一个。这将使复杂度为O(min(A.length,B.length)* 2k)。
要理解这个目的,请考虑A
有1个元素而B
有100个的情况。在这种情况下,我们只会在外部循环中执行一次迭代,并且k内循环中的迭代。
现在考虑A
何时有100个元素,B
有1.在这种情况下,我们将在外循环上执行100次迭代,并在内循环上执行1次迭代。
如果k小于长数组的长度,则在外循环中迭代较短的数组会更有效。
然后,为了便于阅读,我会改变你计算k距离的方法。我写的代码证明了这一点。
这就是我要做的事情:
//not sure what type of array we're dealing with here, so I'll assume int.
int[] toIterate;
int[] toSearch;
if (A.length > B.length)
{
toIterate = B;
toSearch = A;
}
else
{
toIterate = A;
toSearch = B;
}
for (int i = 0; i < toIterate.length; i++)
{
// set j to k away in the negative direction
int j = i - k;
if (j < 0)
j = 0;
// only iterate until j is k past i
for (; (j < toSearch.length) && (j <= i + k); j++)
{
if(toIterate[i] == toSearch[j])
{
System.out.println(toSearch[j]);
}
}
}
您使用jlimit
和ks
可能会有效,但是对于普通程序员来说,处理这样的k距离对于普通程序员来说更容易理解(并且效率稍高)。
答案 4 :(得分:1)
O(N)解决方案(BloomFilters):
这是一个使用bloom过滤器的解决方案(实现来自Guava库)
public static <T> T findCommon_BloomFilterImpl(T[] A, T[] B, Funnel<T> funnel) {
BloomFilter<T> filter = BloomFilter.create(funnel, A.length + B.length);
for (T t : A) {
filter.put(t);
}
for (T t : B) {
if (filter.mightContain(t)) {
return t;
}
}
return null;
}
像这样使用它:
Integer j = Masking.findCommon_BloomFilterImpl(new Integer[]{12, 2, 3, 4, 5222, 622, 71, 81, 91, 10}, new Integer[]{11, 100, 15, 18, 79, 10}, Funnels.integerFunnel());
Assert.assertNotNull(j);
Assert.assertEquals(10, j.intValue());
在O(N)中运行,因为计算Integer的哈希非常简单。所以仍然是O(N),如果你可以将你的元素的散列计算减少到O(1)或小O(K),其中K是每个元素的大小。
O(N.LogN)解决方案(排序和迭代):
排序和遍历数组将引导您进入O(N * log(N))解决方案:
public static <T extends Comparable<T>> T findCommon(T[] A, T[] B, Class<T> clazz) {
T[] array = concatArrays(A, B, clazz);
Arrays.sort(array);
for (int i = 1; i < array.length; i++) {
if (array[i - 1].equals(array[i])) { //put your own equality check here
return array[i];
}
}
return null;
}
当然, concatArrays(~)
在O(N)中。 Arrays.sort(~)
是QuickSort的双轴实现,复杂度为O(N.logN),再次遍历数组为O(N)。
所以我们有O((N + 2).logN)〜&gt; O(N.logN)。
作为一般情况解决方案(没有问题的“k内”条件)比你的好。在您的确切情况下,应该考虑k“接近”N.
答案 5 :(得分:1)
如果数组已经排序,则为简单解决方案
public static void get_common_courses(Integer[] courses1, Integer[] courses2) {
// Sort both arrays if input is not sorted
//Arrays.sort(courses1);
//Arrays.sort(courses2);
int i=0, j=0;
while(i<courses1.length && j<courses2.length) {
if(courses1[i] > courses2[j]) {
j++;
} else if(courses1[i] < courses2[j]){
i++;
} else {
System.out.println(courses1[i]);
i++;j++;
}
}
}
Apache commons collections API以高效的方式完成了这项工作而没有排序
public static Collection intersection(final Collection a, final Collection b) {
ArrayList list = new ArrayList();
Map mapa = getCardinalityMap(a);
Map mapb = getCardinalityMap(b);
Set elts = new HashSet(a);
elts.addAll(b);
Iterator it = elts.iterator();
while(it.hasNext()) {
Object obj = it.next();
for(int i=0,m=Math.min(getFreq(obj,mapa),getFreq(obj,mapb));i<m;i++) {
list.add(obj);
}
}
return list;
}
答案 6 :(得分:1)
使用Java 8的解决方案
static <T> Collection<T> intersection(Collection<T> c1, Collection<T> c2) {
if (c1.size() < c2.size())
return intersection(c2, c1);
Set<T> c2set = new HashSet<>(c2);
return c1.stream().filter(c2set::contains).distinct().collect(Collectors.toSet());
}
使用Arrays :: asList和基元的盒装值:
Integer[] a =...
Collection<Integer> res = intersection(Arrays.asList(a),Arrays.asList(b));
答案 7 :(得分:0)
通用解决方案
public static void main(String[] args) {
String[] a = { "a", "b" };
String[] b = { "c", "b" };
String[] intersection = intersection(a, b, a[0].getClass());
System.out.println(Arrays.toString(intersection));
Integer[] aa = { 1, 3, 4, 2 };
Integer[] bb = { 1, 19, 4, 5 };
Integer[] intersectionaabb = intersection(aa, bb, aa[0].getClass());
System.out.println(Arrays.toString(intersectionaabb));
}
@SuppressWarnings("unchecked")
private static <T> T[] intersection(T[] a, T[] b, Class<? extends T> c) {
HashSet<T> s = new HashSet<>(Arrays.asList(a));
s.retainAll(Arrays.asList(b));
return s.toArray((T[]) Array.newInstance(c, s.size()));
}
<强>输出强>
[b]
[1, 4]