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