- 让
S1
和S2
成为两组整数(它们不一定是不相交的)。- 我们知道 那个
|S1| = |S2| = n
(即每个集合都有n
个整数)。- 每个集合都存储在长度为
n
的数组中,其中 它的整数按升序排序。- 让
k ≥ 1
为整数。- 设计算法以找到 O(n)时间
k
中S1 ∩ S2
个最小整数。
这是我到目前为止所做的:
Intersection
e
中的每个S1
,在O(n)时间内将e
添加到hashset e
中的每个S2
,检查哈希集中是否存在e
e
,请将e
添加到Intersection
Intersection
按排序在O(n)时间 k
整数我是在正确的轨道上吗?
答案 0 :(得分:4)
是的,你肯定是在正确的轨道上,但实际上根本不需要生成哈希表或额外的集合。由于你的两个集合已经排序,你可以简单地通过两个集合运行索引/指针,寻找公共元素。
例如,要查找两个集合中的第一个公共元素,请使用以下伪代码:
start at first index of both sets
while more elements in both sets, and current values are different:
if set1 value is less than set2 value:
advance set1 index
else
advance set2 index
最后,set1 index
将引用一个交叉点,前提是这两个索引都没有超出其各自列表中的最后一个元素。然后,您可以在循环中使用该方法来查找第一个x
交集值。
这是Python 3中的概念证明,它为您提供了两个列表中的前三个数字(2的倍数和3的倍数)。完整的交集将是{0, 6, 12, 18, 24}
,但您会看到它只会提取前三个:
# Create the two lists to be used for intersection.
set1 = [i * 2 for i in range(15)] ; print(set1) # doubles
set2 = [i * 3 for i in range(15)] ; print(set2) # trebles
idx1 = 0 ; count1 = len(set1)
idx2 = 0 ; count2 = len(set2)
# Only want first three.
need = 3
while need > 0:
# Continue until we find next intersect or end of a list.
while idx1 < count1 and idx2 < count2 and set1[idx1] != set2[idx2]:
# Advance pointer of list with lowest value.
if set1[idx1] < set2[idx2]:
idx1 += 1
else:
idx2 += 1
# Break if reached end of a list with no intersect.
if idx1 >= count1 or idx2 >= count2:
break
# Otherwise print intersect and advance to next list candidate.
print(set1[idx1]) ; need -= 1
idx1 += 1 ; idx2 += 1
正如预期的那样输出:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42]
0
6
12
如果你最后需要一个列表而不是只打印出交叉点,你只需在循环之前初始化一个空容器,然后将值附加到它而不是打印它。这会变得更像您提出的解决方案,但具有不需要哈希表或排序的优势。
答案 1 :(得分:0)
创建两个数组,调用大小为arr1
的{{1}}和arr2
,并按整数值按升序填充它们。创建两个索引,称为array_size
和i
,分别用于迭代j
和arr1
并将它们初始化为0.比较每个索引的前两个值数组:如果arr2
小于arr1[0]
,则增加arr2[0]
,否则i
大于arr1[0]
增量arr2[0]
,否则值相交我们可以返回这个值。一旦我们返回k个相交值,我们就可以停止迭代了。在最坏的情况下,如果两组值之间没有交叉,那么这将是i + j,O(n),我们将不得不迭代到每个数组的末尾。
以下是bash中的解决方案:
j
输出:
#!/bin/bash
#-------------------------------------------------------------------------------
# Design an algorithm to find the k smallest integers in S1 ∩ S2 in O(n) time.
#-------------------------------------------------------------------------------
typeset -a arr1 arr2 arr_answer
typeset -i array_size=20 k=5
function populate_arrs {
typeset -i counter=0
while [[ ${counter} -lt ${array_size} ]]; do
arr1[${counter}]=$((${counter} * 2))
arr2[${counter}]=$((${counter} * 3))
counter=${counter}+1
done
printf "%8s" "Set1: "; printf "%4d" ${arr1[*]}; printf "\n"
printf "%8s" "Set2: "; printf "%4d" ${arr2[*]}; printf "\n\n"
}
function k_smallest_integers_main {
populate_arrs
typeset -i counter=0 i=0 j=0
while [[ ${counter} -lt ${k} ]]; do
if [[ ${arr1[${i}]} -eq ${arr2[${j}]} ]]; then
arr_answer[${counter}]=${arr1[${i}]}
counter=${counter}+1; i=${i}+1; j=${j}+1
elif [[ ${arr1[${i}]} -lt ${arr2[${j}]} ]]; then
i=${i}+1
else
j=${j}+1
fi
done
printf "%8s" "Answer: "; printf "%4d" ${arr_answer[*]}; printf "\n"
}
k_smallest_integers_main
答案 2 :(得分:-2)
在Python中:
i1= 0; i2= 0
while k > 0 and i1 < n and i2 < n:
if S1[i1] < S2[i2]:
i1+= 1
elif S1[i1] > S2[i2]:
i2+= 1
else:
Process(S1[i1], S2[i2])
i1+= 1; i2+= 1
k-= 1
如果交叉点中没有足够多的元素,执行将对k
的{{1}}次调用执行次数。