[编程题] 用户喜好 时间限制:3秒
空间限制:262144K
为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为k。因为一些特殊的原因,不会出现一个查询的用户区间完全覆盖另一个查询的用户区间(不存在L1<=L2<=R2<=R1)。
输入描述: 输入: 第1行为n代表用户的个数 第2行为n个整数,第i个代表用户标号为i的用户对某类文章的喜好度
第3行为一个正整数q代表查询的组数
第4行到第(3+q)行,每行包含3个整数l,r,k代表一组查询,即标号为l<=i<=r的用户中对这类文章喜好值为k的用户的个数。 数据范围n
<= 300000,q<=300000 k是整型输出描述: 输出:一共q行,每行一个整数代表喜好值为k的用户的个数
输入例子1:
5
1 2 3 3 5
3
1 2 1
2 4 5
3 5 3输出例子1: 1 0 2
例子说明1: 样例解释: 有5个用户,喜好值为分别为1、2、3、3、5, 第一组询问对于标号[1,2]的用户喜好值为1的用户的个数是1
第二组询问对于标号[2,4]的用户喜好值为5的用户的个数是0 第三组询问对于标号[3,5]的用户喜好值为3的用户的个数是2
这道题审题后的第一个思路就是使用暴力破解,使用两层for循环遍历整个二维数组。但是使用以后会发现,无论如何优化都只会有50%的编译通过率,因为暴力破解的时间复杂度太大,复杂度为O(n^2)
既然暴力破解无法在系统给出的时间范围内求得所有解,那就换一个思路,把时间复杂度降低为O(n*logn),创建一个使用拉链法存储数据的哈希表。
直接帖代码了:
public class Ex1{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n,q;
int box=0;
//int array[][];
n=sc.nextInt();
//创建一个map
Map<Integer,List<Integer>> myMap=new HashMap<Integer,List<Integer>>();
List<Integer> myList;
for(int i=0;i<n;i++){
box=sc.nextInt();
//判断这个值是否存在于map的key中
if(myMap.get(box)==null){
//不存在,就向添加List
myList = new LinkedList<Integer>();
myList.add(i);
myMap.put(box,myList);
}
else{
//存在就把当前list拿出来
//然后追加当前index
myList=myMap.get(box);
myList.add(i);
}
}
q=sc.nextInt();
for(int i=0;i<q;i++){
int a,b,c;
int count=0;
a=sc.nextInt();
b=sc.nextInt();
c=sc.nextInt();
//根据c去map中找到对应的下表list
myList= myMap.get(c);
if(myList==null){
System.out.println("0");
continue;
}
//循环这个list
//得到的是对应的所有下标
for(int j= 0 ; j < myList.size() ; j++) {//内部不锁定,效率最高,但在多线程要考虑并发操作的问题。
if(a-1<= myList.get(j).intValue()&&myList.get(j).intValue()<=b-1){
count++;
}
}
System.out.println(count);
}
}
}
为了方便,直接使用了java自带的两个类Map和List
主要使用的方法是
Map的get 和put
List的get和add