我在接受采访时被问到这个问题。
我一直在努力为这个问题找到一个优雅的算法,但还没有能够这样做。
给出一个人员列表(用数字表示 - id' s)及其技能集如下:
C:1,8,12,14
C ++:3,7,8,12,15
perl:1,2,3,8
Ruby:14,23
根据技能列表,返回与所需技能组匹配的ID:
[EG]
技能组合:C& C ++ 答案是8,12
技能组合:C,C ++,Perl - 匹配至少2种技能 答案是1,3,8,12
id的列表最初是未分类的,但我从排序开始。 天真的方法是获取一个列表(比如第二个例子中的c ++)并将其与另一个使用排序顺序的列表(比如Java)进行比较。
是否有算法或更好的方法?
答案 0 :(得分:0)
取决于技能的数量。如果它很小,我会使用素数。更多的是:
创建表skills[n]
(其中n是用户数)。填写1
s。然后,如果用户知道第一技能(在这种情况下是C)乘以第一素数(2),如果他知道第二技能乘以第二素数等等。
然后,如果您想查找用户i
是否知道第二技能(C ++),只需检查是否skills[i]%3==0
实施例: 寻找技能价值: 用户1知道技能1(C)和技能3(Perl),这意味着他的技能值是1 * 2 * 5 = 10。用户2知道技能3,因此他的技能值是1 * 5.
查找可以使用C,C ++,Perl匹配2的所有用户:
for(int i=0;i<n;i++){
int howMany=0;
if(skill[i]%2)==0)
howMany++;
if(skill[i]%5)==0)
howMany++;
if(skill[i]%7)==0)
howMany++;
if(howMany>=2)
addToResult(i);
}
或者,您可以创建一个二维数组,其中列对应于人和行对技能。如果value设置为1,则表示人员知道如何使用该技能,如果设置为0,则不会。然后,只需添加您需要的所有行的值,并找到合适的用户。
示例:
C 1 | 0 | 0 |
C++ 0 | 0 | 1 |
PERL 1 | 1 | 1 |
让我们找一个知道C的人,Perl - 我们添加第1行和第3行的所有值,我们得到
SUM 2 | 1 | 1 |
只有第1列的值为&gt; = 2,这意味着它是唯一符合条件的人。 现在,让我们尝试找一个使用C,C ++和PERL,匹配2
的人SUM 2 | 1 | 2
我们现在知道用户1和用户3的值>&gt; = 2,因此他们符合这些标准。
答案 1 :(得分:0)
这是一种有效的算法: -
- 为每项技能使用ID的HashSet
- 要检查ID是否具有技能,只需检查HashSet
醇>
注意:强>
此算法为O(n*S)
,其中n
为人数,S
为所需技能数。我不认为有更快的算法。
修改强>
除了搜索所有n个人之外,您还可以仅检查至少具有所需技能的人员。在许多情况下,这将节省大量的计算时间。