问题描述
某游戏,每一局需要多个玩家参与。若发现有两玩家同时参与过至少两局游戏,即认为这两个玩家互为队友。 现已知若干玩家(玩家id, int)、若干局游戏(游戏id, int)的历史记录,求某一个给定玩家的所有队友。 如已知历史记录如下:
| 玩家ID | 游戏ID |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 4 |
| 3 | 2 |
| 4 | 1 |
| 4 | 2 |
| 5 | 2 |
| 5 | 3 |
思路
把给定玩家对应的所有游戏存进HashSet中去,然后将所给的历史记录二维数组按照玩家序号从小到大排序,这样每个人所有游戏数据都会挨在一起,从头遍历这个二维数组,对每个人的历史记录做判断,如果它的游戏和指定玩家的游戏重叠大于等于2就记录下来,枚举完一个人之后更新循环变量,时间复杂度为O(1). `
public static int[] solution(int id, int num, int[][] array) {
Set<Integer> set=new HashSet<>();
int[] ans=new int[num];
int cnt=0;
//按照玩家序号排序
Arrays.sort(array,new Comparator<int[]>() {
public int compare(int[] a,int[] b){
return a[0]-b[0];
}
});
//将目标玩家的所有游戏加入SET中去,方便后面比较
for(int i=0;i<num;i++){
if(array[i][0]==id){
set.add(array[i][1]);
}
}
for(int i=0,j;i<num;i++){
if(array[i][0]==id)
continue;
int common=0;
//循环到要么到达最后,要么到下一位玩家
for(j=i;(j<num)&&(array[j][0]==array[i][0]);j++){
if(set.contains(array[j][1])){
common++;
}
}
//符合题意,计入答案
if(common>=2){
ans[cnt++]=array[i][0];
i=j-1;
}
}
int[] res=Arrays.copyOf(ans, cnt);
return res;
} `