[アルゴリズム]ランキングの検索
32780 ワード
質問する
質問リンク
これは、データの後にクエリーを処理する問題です.
簡単に文字列に切って、数えておけばいいと思っていました.
インプリメンテーション
挑戦する方法は、列数で並べてカウントダウンを行うことです.// 간단한 처리를 위해 문자를 각각 012로 매칭함.
int[][][][][] data;
データを記入すると問題になります.
例:
100点以上のすべてのデータを得るためには,簡単に考えれば順次巡回が可能である.
しかし、一見非効率的だ.
各インデックスにデータの数があるとします.次のようにします.
0 1 2 3 4 5 6 7 8 9 ...
0 0 1 0 0 2 0 0 0 0 ...
では、2より大きいデータを探すためには[2,data.length()]を求める必要があり、真ん中に0のデータが挟まっていると困る.
(セグメントツリーをしばらく使うべきだと思いますが、すべての組み合わせのツリーを作成するのはメモリがかかりすぎて、実装も難しいかもしれません.)
だから配列に追加する方法でデータを入れるべきだと知っています.
では[2,5,5,10,15,20]とともにデータが存在する場合,5の最小インデックスを求めれば5以上のデータ数が分かる.
これはバイナリ検索によって実現できる.
(javaでは、複数の配列を使用してソートする場合は、各次元を比較する必要があります.
したがって、複数の配列を使用するのではなく、Stringに変換してMapに変換します.)
時間の複雑さ
挑戦する方法は、列数で並べてカウントダウンを行うことです.
// 간단한 처리를 위해 문자를 각각 012로 매칭함.
int[][][][][] data;
データを記入すると問題になります.例:
100点以上のすべてのデータを得るためには,簡単に考えれば順次巡回が可能である.
しかし、一見非効率的だ.
各インデックスにデータの数があるとします.次のようにします.
0 1 2 3 4 5 6 7 8 9 ...
0 0 1 0 0 2 0 0 0 0 ...
では、2より大きいデータを探すためには[2,data.length()]を求める必要があり、真ん中に0のデータが挟まっていると困る.
(セグメントツリーをしばらく使うべきだと思いますが、すべての組み合わせのツリーを作成するのはメモリがかかりすぎて、実装も難しいかもしれません.)
だから配列に追加する方法でデータを入れるべきだと知っています.
では[2,5,5,10,15,20]とともにデータが存在する場合,5の最小インデックスを求めれば5以上のデータ数が分かる.
これはバイナリ検索によって実現できる.
(javaでは、複数の配列を使用してソートする場合は、各次元を比較する必要があります.
したがって、複数の配列を使用するのではなく、Stringに変換してMapに変換します.)
時間の複雑さ
最初から-セルのすべての状況を考慮した数を先に含めるかどうか.
または、後でクエリーを処理するときに複数の計算を選択できます.
複数計算クエリー
まず、入力データをmapに処理するには、入力データの個数に等しい時間が必要である.(5万)
クエリーは、cpp、java、pythonのようにすべての複数の選択を処理する必要があるため、各基数を乗算する必要があります.
では、3 x 2 x 2 x 2 x 2 xクエリ数(10万)の大きなクエリを処理する必要があります.
=>24 x 10万=240万
各クエリーはバイナリツリーで処理されます.
リスト長をn(最大5万)と呼ぶとlogn(最大16)と同じ時間がかかります.
すなわち、5 x 10^4 x 240 x 10^4 x 16=19200 x 10^8(19200秒)
△このように解いても、効率テストに合格した.
可能なすべての入力を挿入
ただし、入力データを初めて処理するときに重複データまで入れると
5万x 24の時間がかかりますが
クエリーは一度だけ処理できます.10万x 16
最終的な時間複雑度は5 x 10^4 x 10 x 10^4 x 16=800 x 10^8(800秒)である.
コード#コード# import java.util.*;
class Solution {
public int[] solution(String[] info, String[] query) {
Map<String, List<Integer>> map=new HashMap<>();
setMap(map,info);
sortMap(map);
int[] ans = solve(query,map);
return ans;
}
void setMap(Map<String, List<Integer>> map,String[] info){
for(String inf:info){
StringTokenizer stk=new StringTokenizer(inf);
StringBuilder sb=new StringBuilder();
for(int i=0;i<4;i++) sb.append(stk.nextToken());
int score=Integer.parseInt(stk.nextToken());
// push to map
if(!map.containsKey(sb.toString())){
List<Integer> arr=new ArrayList<>();
arr.add(score);
map.put(sb.toString(),arr);
}
else{
List<Integer> arr = map.get(sb.toString());
arr.add(score);
}
}
}
void sortMap(Map<String, List<Integer>> map){
for(List<Integer> arr:map.values()){
Collections.sort(arr);
}
}
int[] solve(String[] query, Map<String, List<Integer>> map){
List<String> listA=new ArrayList<>();
List<String> listB=new ArrayList<>();
List<String> listC=new ArrayList<>();
List<String> listD=new ArrayList<>();
int[] ret=new int[query.length];
int score;
int idx=0;
for(String str:query){
String[] strList=str.split(" and | ");
listA.clear();
String queryA=strList[0];
if(queryA.equals("-")) {listA.add("cpp");listA.add("java");listA.add("python");}
else listA.add(queryA);
listB.clear();
String queryB=strList[1];
if(queryB.equals("-")) {listB.add("backend");listB.add("frontend");}
else listB.add(queryB);
listC.clear();
String queryC=strList[2];
if(queryC.equals("-")) {listC.add("junior");listC.add("senior");}
else listC.add(queryC);
listD.clear();
String queryD=strList[3];
if(queryD.equals("-")) {listD.add("chicken");listD.add("pizza");}
else listD.add(queryD);
score=Integer.parseInt(strList[4]);
int tmp=0;
for(String strA:listA){
for(String strB:listB){
for(String strC:listC){
for(String strD:listD){
StringBuilder sb=new StringBuilder();
sb.append(strA);sb.append(strB);
sb.append(strC);sb.append(strD);
// 이진탐색으로 tmp 에 더함
tmp+=getLowerBound(sb.toString(),score,map);
}
}
}
}
ret[idx++]=tmp;
}
return ret;
}
int getLowerBound(String query,int score,Map<String, List<Integer>> map){
// map 에서 score list 받기
List<Integer> scoreList;
if(!map.containsKey(query)) return 0;
scoreList=map.get(query);
// scoreList 가 있다면 로어 바운드로 score 이상값중 낮은 인덱스 찾기
int s=0,e=scoreList.size()-1;
int lbound=-1;
int ret=0;
while(s<=e){
int mid=(s+e)/2;
if(scoreList.get(mid)>=score) {e=mid-1;lbound=mid;}
else s=mid+1;
}
if(lbound==-1) return 0;
else return (scoreList.size()-lbound);
}
}
Reference
この問題について([アルゴリズム]ランキングの検索), 我々は、より多くの情報をここで見つけました
https://velog.io/@shininghyunho/알고리즘-순위-검색
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import java.util.*;
class Solution {
public int[] solution(String[] info, String[] query) {
Map<String, List<Integer>> map=new HashMap<>();
setMap(map,info);
sortMap(map);
int[] ans = solve(query,map);
return ans;
}
void setMap(Map<String, List<Integer>> map,String[] info){
for(String inf:info){
StringTokenizer stk=new StringTokenizer(inf);
StringBuilder sb=new StringBuilder();
for(int i=0;i<4;i++) sb.append(stk.nextToken());
int score=Integer.parseInt(stk.nextToken());
// push to map
if(!map.containsKey(sb.toString())){
List<Integer> arr=new ArrayList<>();
arr.add(score);
map.put(sb.toString(),arr);
}
else{
List<Integer> arr = map.get(sb.toString());
arr.add(score);
}
}
}
void sortMap(Map<String, List<Integer>> map){
for(List<Integer> arr:map.values()){
Collections.sort(arr);
}
}
int[] solve(String[] query, Map<String, List<Integer>> map){
List<String> listA=new ArrayList<>();
List<String> listB=new ArrayList<>();
List<String> listC=new ArrayList<>();
List<String> listD=new ArrayList<>();
int[] ret=new int[query.length];
int score;
int idx=0;
for(String str:query){
String[] strList=str.split(" and | ");
listA.clear();
String queryA=strList[0];
if(queryA.equals("-")) {listA.add("cpp");listA.add("java");listA.add("python");}
else listA.add(queryA);
listB.clear();
String queryB=strList[1];
if(queryB.equals("-")) {listB.add("backend");listB.add("frontend");}
else listB.add(queryB);
listC.clear();
String queryC=strList[2];
if(queryC.equals("-")) {listC.add("junior");listC.add("senior");}
else listC.add(queryC);
listD.clear();
String queryD=strList[3];
if(queryD.equals("-")) {listD.add("chicken");listD.add("pizza");}
else listD.add(queryD);
score=Integer.parseInt(strList[4]);
int tmp=0;
for(String strA:listA){
for(String strB:listB){
for(String strC:listC){
for(String strD:listD){
StringBuilder sb=new StringBuilder();
sb.append(strA);sb.append(strB);
sb.append(strC);sb.append(strD);
// 이진탐색으로 tmp 에 더함
tmp+=getLowerBound(sb.toString(),score,map);
}
}
}
}
ret[idx++]=tmp;
}
return ret;
}
int getLowerBound(String query,int score,Map<String, List<Integer>> map){
// map 에서 score list 받기
List<Integer> scoreList;
if(!map.containsKey(query)) return 0;
scoreList=map.get(query);
// scoreList 가 있다면 로어 바운드로 score 이상값중 낮은 인덱스 찾기
int s=0,e=scoreList.size()-1;
int lbound=-1;
int ret=0;
while(s<=e){
int mid=(s+e)/2;
if(scoreList.get(mid)>=score) {e=mid-1;lbound=mid;}
else s=mid+1;
}
if(lbound==-1) return 0;
else return (scoreList.size()-lbound);
}
}
Reference
この問題について([アルゴリズム]ランキングの検索), 我々は、より多くの情報をここで見つけました https://velog.io/@shininghyunho/알고리즘-순위-검색テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol