1. 程式人生 > >2018秋招校招後端方向(第二批)

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!!