2018秋招校招后端方向(第二批)

用户喜好

  为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为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

解答:

import java.util.*;
public class Main{
  public static void main(String[] args) throws Exception{
    int num;
    Scanner sc = new Scanner(System.in);
    num=sc.nextInt();  //n个用户
    int[] arr= new int[num];
    for(int i=0;i<num;i++)
      arr[i]=sc.nextInt();  //用户的喜好值
    int leng= sc.nextInt();  //查询组数
    int[] lrk= new int[3];    
    for(int i=0;i<leng;i++){
      int temp=0;
      for(int j=0;j<3;j++)
        lrk[j]=sc.nextInt();  //l,r,k
      for(int j=lrk[0]-1;j<lrk[1];j++){  //在l<=j<=r中,依次查找值为k的
        if(arr[j]==lrk[2])
          temp=temp+1;
      }
      System.out.println(temp);
    }
  }
}

运行结果:

运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大
case通过率为50.00%

然后呢,我就想到可能是代码的

for(int j=lrk[0]-1;j<lrk[1];j++){  //在i<=j<=r中,依次查找值为k的
  if(arr[j]==lrk[2])
    temp=temp+1;
}

运行时间过长了,然后试了改成二分查找。

import java.util.*;
public class Main{
  public static void main(String[] args) throws Exception{
    int num;
    Scanner sc = new Scanner(System.in);
    num=sc.nextInt();
    int[] arr= new int[num];
    for(int i=0;i<num;i++)
      arr[i]=sc.nextInt();
    int leng= sc.nextInt();
    int[] lrk= new int[3];
    for(int i=0;i<leng;i++){
      int temp=0,left=0,right=0,mid=0,target=0;
      for(int j=0;j<3;j++)
        lrk[j]=sc.nextInt();
      left=lrk[0]-1;
      right=lrk[1]-1;
      target=lrk[2];
      int[] sonarr = new int[right-left+1];
      for(int j=0;j<right-left+1;j++)
        sonarr[j]=arr[left+j];
      Arrays.sort(sonarr);     //对l-r间的数据排序,后续进行二分查找,若对整个arr排序,则是错误的,因为喜好值对应的人的id变了,对在[l,r]间数据排序则无影响,因为k值在这里面查找,顺序无影响
      right=right-left;
      left=0;
      while(sonarr[left]<target&&sonarr[right]>target){
        mid=(left+right)/2;
        if(sonarr[left+1]==target||sonarr[right-1]==target)
          break;
        else if(sonarr[mid]<target)
          left=mid;
        else if(sonarr[mid]>target)
          right=mid;
      }
      for(int j=left;j<=right;j++){
        if(sonarr[j]==target)
          temp=temp+1;
      }
      System.out.println(temp);
    }
  }
}

结果程序通过率为0.00%,(┬_┬)

啊,做了一个小时心态崩了,没办法,看看别人的吧.....看了一遍大佬的思路,然后自己又做了一遍..

思路就是,把喜好值(key)相同的人放在一个value里,比如(1,3,3,5,6,6,6),那么喜好值(key)为3的人有2,3,所以map里存放的数据为{(1,“1”),(3,“2,3”),(5,“4”),(6,“5,6,7”)}

然后通过k=key的方式,依次读取value中的值是否是  l<=value(i)<=r,若是,则temp+1。若没找到这个key,那么那么输出temp=0。

import java.util.*;
public class Main{
  public static void main(String[] args) throws Exception{
    Scanner in =new Scanner(System.in);
    int peo= in.nextInt();
    int[] arr = new int[peo];
    for(int i=0;i<peo;i++)
      arr[i]=in.nextInt();
    Map<Integer,ArrayList<Integer>> map = new HashMap();
    ArrayList<Integer> list;
    for(int i=0;i<peo;i++){
      int key=arr[i];
      int value=i+1;
      list = new ArrayList<Integer>();
      if(map.containsKey(key)){
        list=map.get(key);
        list.add(value);
      }else {
        list.add(value);
        map.put(key,list);
      }
    }
    int num=in.nextInt();
    for(int i=0;i<num;i++){
      int temp=0;
      int l=in.nextInt();
      int r=in.nextInt();
      int k=in.nextInt();
      list = new ArrayList<Integer>();
      if(!map.containsKey(k))
        System.out.println(temp);
      else{
        list=map.get(k);
        for(int x:list){
          if(l<=x&&x<=r)
          temp=temp+1;
        }
        System.out.println(temp);
      }
   }
  }
}

ACCEPT!!

猜你喜欢

转载自www.cnblogs.com/zhuii/p/9951437.html
今日推荐