プログラム・デザイナのランキング検索
21894 ワード
マジシャンです
比喩問題では、「ある表でSELECTを求めるときの結果数」とあまり差がありません.
ただし,WHERE節には複数の条件があり,与えられたデータは表形式ではなくStringである.効率テストもあります.
方法
初期の方法は、各行がボランティア情報を検索し、2階建ての砲口にいくつかのif条件を加えることだった.精度テストに合格しましたが、効率テストがタイムアウトしました.
別の方法を考え出そうと…!!
1.HashMapに対応するクエリーを検索させる
HashMapでは、そのqueryと同じ内容があれば数字を計算し、なければ0と呼ぶ.
では、HashMapをinfo配列で埋め込むには、どうすればいいのでしょうか.
サンプルデータを取得します
「java backend junior pizza 150」では、前の4つの単語と後の数字を分けて見ると、「javabendjunior pizza」をキーとして150を値とすれば、完全にHashMapに入れることができます.
ただし、キーが同じでvalueが異なる重複が発生する可能性があります.これに対応するためにvalue形式をListとする.
ただし、上記の例のデータ「javabackendjunior pizza」は「-backed-pizza」として参照することもできます.また、「java---」と参照することもできます.つまり、javabackendjuniorpizaを参照するには、「-」が含まれているすべての場合、HashMapに入れる必要があります.
「-」のすべての状況をどのように取得しますか?-->部分集合を利用すればいい!
今では上の方法でHashMapを充填しています.
2.リストで質問点数以上の数字を求める
「---」のようなキーはvalueのリストのサイズが大きいに違いない.そのリストでは、あなたの点数があなたの質問点数より大きい場合は、数を求めます.良い方法はないですか?
リストを並べ替えた後,二分探索により,クエリスコア以上の値が最初に現れる点のインデックスを取得し,リストの大きさからインデックス値を減算することで,クエリ条件に合致する応募者の数を得ることができる.
(1,2,3,4,4,6,7,8)リストがある場合、1つ数えて4以上あれば、4以上で初めて出てくるインデックスは3です.Listの大きさは9なので、9-3と言えば6です.
求めた値を順番に答えに入れればいいです.
コード#コード#
import java.util.*;
class Solution {
public int[] solution(String[] info, String[] query) {
int[] answer = new int[query.length];
HashMap<String, List<Integer> > hm = new HashMap<>();//해시맵
boolean[] chk = new boolean[4];//부분집합에 쓰이는 boolean 배열
//recur를 통해 부분집합의 경우의 수 만큼 해시맵에 넣어준다.
for(int i = 0 ; i < info.length; i++){
String[] infos = info[i].split(" ");
recur(hm, infos, 0, chk);
}
//value의 List들을 다 정렬 해준다.
for(String qr : hm.keySet()){
Collections.sort(hm.get(qr));
}
//해당 문의가 해시맵에 있는지 확인하고
for(int i = 0; i < query.length; i++){
String[] x = query[i].split(" ");
StringBuilder sb = new StringBuilder();
sb.append(x[0]).append(x[2]).append(x[4]).append(x[6]);
String qr = sb.toString();
int num = Integer.parseInt(x[7]);
if(!hm.containsKey(qr)) continue;
else{
//해당 문의가 해시맵에 있다면, 문의 점수이상의 점수가 처음으로 나오는 지점을 이분탐색을 통해 구한다.
List<Integer> ml = hm.get(qr);
answer[i] = myBSearch(ml, num);
}
}
return answer;
}
//이분 탐색 메소드
private static int myBSearch(List<Integer> ml, int num){
int start = 0;
int end = ml.size();
while(start < end){
int mid = (start + end) / 2;
if(ml.get(mid) < num)
start = mid + 1;
else
end = mid;
}
//이분 탐색후 List의 크기 - 해당 점수가 처음으로 나온 인덱스의 값은
//해당 점수보다 이상인 점수들의 개수이므로 이 값을 바로 리턴하게 해줌
return ml.size() - end;
}
//부분 집합 메소드
private static void recur(HashMap<String, List<Integer> > hm, String[] x, int cnt, boolean[] chk){
if(cnt == 4){
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 4 ; i++){
if(chk[i]) sb.append(x[i]);
else sb.append("-");
}
String res = sb.toString();
//이미 해시맵에 있다면 List에 add해준다.
if(hm.containsKey(res)){
hm.get(res).add(Integer.parseInt(x[4]));
}else{
//없다면 새로 List를 만들어 해시맵에 넣어준다.
List<Integer> ml = new ArrayList<>();
ml.add(Integer.parseInt(x[4]));
hm.put(res, ml);
}
return;
}
chk[cnt] = true;
recur(hm, x,cnt+1 ,chk);
chk[cnt] = false;
recur(hm, x,cnt+1 ,chk);
}
}
Reference
この問題について(プログラム・デザイナのランキング検索), 我々は、より多くの情報をここで見つけました https://velog.io/@fufru/프로그래머스-순위-검색テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol