我有一个问题是在两个数组中找到不同大小的公共元素。
获取大小为A1
的数组n
和大小为A2
的数组m
以及m != n
到目前为止,我已经尝试逐个迭代列表并将元素复制到另一个列表。如果元素已包含标记,但我知道这不是一个好的解决方案。
答案 0 :(得分:28)
对数组进行排序。然后用两个指针迭代它们,总是推进指向较小值的指针。当他们指向相等的值时,您就有一个共同的价值。这将是O(n + m),其中n和m是两个列表的大小。它就像merge sort中的合并一样,但只有在指向的值相等时才产生输出。
def common_elements(a, b):
a.sort()
b.sort()
i, j = 0, 0
common = []
while i < len(a) and j < len(b):
if a[i] == b[j]:
common.append(a[i])
i += 1
j += 1
elif a[i] < b[j]:
i += 1
else:
j += 1
return common
print 'Common values:', ', '.join(map(str, common_elements([1, 2, 4, 8], [1, 4, 9])))
输出
Common values: 1, 4
如果元素不具有可比性,则将一个列表中的元素抛出到散列映射中,并根据散列映射检查第二个列表中的元素。
答案 1 :(得分:13)
如果你想提高效率,我会将较小的数组转换为hashset,然后迭代较大的数组并检查当前元素是否包含在hashset中。与排序数组相比,散列函数是有效的。排序数组很昂贵。
这是我的示例代码
import java.util.*;
public class CountTest {
public static void main(String... args) {
Integer[] array1 = {9, 4, 6, 2, 10, 10};
Integer[] array2 = {14, 3, 6, 9, 10, 15, 17, 9};
Set hashSet = new HashSet(Arrays.asList(array1));
Set commonElements = new HashSet();
for (int i = 0; i < array2.length; i++) {
if (hashSet.contains(array2[i])) {
commonElements.add(array2[i]);
}
}
System.out.println("Common elements " + commonElements);
}
}
输出:
共同元素[6,9,10]
答案 2 :(得分:2)
将A2数组放入HashSet中,然后遍历A1;如果当前元素在集合中,则它是一个公共元素。这需要O(m + n)时间和O(min(m,n))空间。
答案 3 :(得分:1)
在APL中:
∪A1∩A2
示例:
A1←9, 4, 6, 2, 10, 10
A1
9 4 6 2 10 10
A2←14, 3, 6, 9, 10, 15, 17, 9
A2
14 3 6 9 10 15 17 9
A1∩A2
9 6 10 10
∪A1∩A2
9 6 10
答案 4 :(得分:0)
看起来像嵌套循环:
commons = empty
for each element a1 in A1
for each element a2 in A2
if a1 == a2
commons.add(a1)
如果阵列具有相同的大小,则完全无关紧要。
根据所使用的语言和框架,设置操作可能会派上用场。
答案 5 :(得分:0)
尝试heapifying两个数组,然后合并以找到交集。
Java示例:
public static <E extends Comparable<E>>List<E> intersection(Collection<E> c1,
Collection<E> c2) {
List<E> result = new ArrayList<E>();
PriorityQueue<E> q1 = new PriorityQueue<E>(c1),
q2 = new PriorityQueue<E>(c2);
while (! (q1.isEmpty() || q2.isEmpty())) {
E e1 = q1.peek(), e2 = q2.peek();
int c = e1.compareTo(e2);
if (c == 0) result.add(e1);
if (c <= 0) q1.remove();
if (c >= 0) q2.remove();
}
return result;
}
有关合并的更多示例,请参阅this question。
答案 6 :(得分:0)
我所提供的复杂性是O(N*M + N)
。
另请注意,它是 Pseudocode C并且它提供了不同的值。
例如。[1,1,1,2,2,4]
和[1,1,1,2,2,2,5]
将返回[1,2]
复杂性是
N*M
循环的for
原因
+ N
检查原因ArrayCommon[]
是否已存在n
大小,Array2[]
包含重复Array1[]
部分的数据假设N是较小数组的大小(N int Array1[m] = { Whatever };
int Array2[n] = { Whatever };
int ArrayCommon[n] = { };
void AddToCommon(int data)
{
//How many commons we got so far?
static int pos = 0;
bool found = false;
for(int i = 0 ; i <= pos ; i++)
{
//Already found it?
if(ArrayCommon[i] == data)
{
found = true;
}
}
if(!found)
{
//Add it
ArrayCommon[pos] = data;
pos++;
}
}
for(int i = 0 ; i < m ; i++)
{
for(int j = 0 ; j < n ; j++)
{
//Found a Common Element!
if(Array1[i] == Array2[j])
AddToCommon(Array1[i]);
}
}
答案 7 :(得分:0)
在Python中,你会写set(A1).intersection(A2)
。这是最佳的O(n + m)。
但你的问题有些含糊不清。 A1 = [0,0],A2 = [0,0,0]的结果是什么?对你的问题有合理的解释,在最终数组中给出1,2,3或6个结果 - 你的情况需要什么?
答案 8 :(得分:0)
我使用Set intersection解决了这个问题。它非常优雅。尽管我没有分析时间复杂度,但它可能在合理的范围内。
public Set FindCommonElements(Integer[] first, Integer[] second)
{
Set<Integer> set1=new HashSet<Integer>(Arrays.asList(first));
Set<Integer> set2=new HashSet<Integer>(Arrays.asList(second));
// finds intersecting elements in two sets
set1.retainAll(set2);
return set1;
}
答案 9 :(得分:-2)
class SortedArr
def findCommon(a,b)
j =0
i =0
l1=a.length
l2=b.length
if(l1 > l2)
len=l1
else
len=l2
end
while i < len
if a[i].to_i > b[j].to_i
j +=1
elsif a[i].to_i < b[j].to_i
i +=1
else
puts a[i] # OR store it in other ds
i +=1
j +=1
end
end
end
end
t = SortedArr.new
t.findCommon([1,2,3,4,6,9,11,15],[1,2,3,4,5,12,15])