일단 나는 이런 문제는 무조건 정수형으로 변환하여 푸는 것을 선호한다..
문제에서는 초단위의 경우 최대 소수점 셋째 자리까지로 설정을 해 주었기 때문에, Double 타입으로 변환후 x1000을 할 수 있다.
각 task의 시작시간 ~ 요청 완료 시간 까지를 milisec단위로 변환한 timeLines 배열을 생성한다.
class Solution {
int[][] timeLines;
public int solution(String[] lines) {
int answer = 0;
int lLen = lines.length; // task의 개수
// timeLines : 시작시간 , 완료시간
timeLines = new int[lLen][2];
convertLines(lines);
// 구하기 : 모든 완료시간을 iterate하면서, 해당시간 + 1000 - 1 이, 어떤 작업의 시작시간 이상이면 count를 한다
int max = 0,cnt = 0;
int criteria = 0; // 기준이 되는 완료시간
for(int i =0 ; i<lLen;i++){
criteria = timeLines[i][1]+1000-1;
cnt = 1;
for(int j=i+1;j<lLen;j++){
if(timeLines[j][0]<=criteria)cnt++;
}
max = Math.max(max,cnt);
}
answer = max;
return answer;
}
public void convertLines(String[] lines){
String line = null;
int t = 0; // 요청완료시간 정보를 milisec 로 변환한 정보
for(int i =0;i<lines.length;i++){
line = lines[i];
String[] times = line.split(" "); // times[2] 는 처리하는데에 걸린 시간
String[] compT = times[1].split(":"); // 요청 완료 시간 관련 정보
// compT[0] 은 hh , compT[1]은 mm , compT[2]는 ss.sss
t = Integer.parseInt(compT[0])*3600;
t += Integer.parseInt(compT[1])*60;
t *= 1000;
t += (int)(Double.parseDouble(compT[2])*1000);
timeLines[i][1] = t; // 요청완료 시간 기록
timeLines[i][0] = t - ((int)(Double.parseDouble(times[2].split("s")[0])*1000) )+ 1; // 요청 시작 시간
// System.out.println(timeLines[i][0]+"~"+timeLines[i][1]);
}
}
}
[시간][분][초][밀리세컨드]
먼저 정규표현식을 잘 쓸 줄 알아야 겠다.
[ 띄어쓰기를 중심 ] 으로 split한다 "2016-09-15","hh:mm:ss.sss","Ts"
날짜 버리고
"hh:mm:ss.sss" 를 ":"중심으로 split한다.
Ts는 substring을 사용해 s를 없애고 이 String을 double로 변환한다. 이때 주의해야할 점이있다.
"1초" 가 중요하고 , 나는 double형으로 할 경우 혼란이 생길 것 같지만 그게 더 편할 것 같긴 하다. s 단위로 저장한다.
나는 s로 변환 후 —> x1000을 해서 ms단위로 저장하겠다. 24X60x60x1000 =86400000 이기 때문에 int 타입으로 저장 가능하다.
시간이 hh:mm:ss.sss 이기 때문에,
hh x 3600 + mm x 60 + ss.sss 를 저장한다. (":" 를 기준으로 split한다)
ss.sss와 같은 String을 바로 Double로 변환 후 —> 1000을 곱하는 방식을 택했다
💥이 때, Double.parseDouble(String s) 사용시 지수 형식으로 나오게 되기 때문에, 그렇지 않게 하기 위하여 NumberFormat을 사용하였다.
각 로그에 대한 시작시간, 끝 시간에 대한 array를 각각 생성한다.
전체탐색을 사용 한다. 전체 로그 개수가 2000개 정도 밖에 안 되기 때문에 전체탐색을 해도 괜찮은 문제였다. N^2이라하더라도 4백만개 정도이기 때문에 괜찮다.
문제에서 [ 끝 시간 ] 을 기준으로 [오름차순 ] 인 정보를 주었다는것과 + "완료된 것이 아니어도" 카운트 한다는게 중요하다
end array를 for문을 이용하여 돈다.
public static void set(int[] start, int[] end,String[] lines){
for(int i=0;i<lines.length;i++){
int endTime=0;
int startTime=0;
String[] seg = lines[i].split(" ");
// Drop seg[0] --> seg[1] : hh:mm:ss.sss --> seg[2] : ?s
String[] times = seg[1].split(":");
int hour = Integer.parseInt(times[0]);
int min = Integer.parseInt(times[1]);
int secmsec = (int)(Double.parseDouble(times[2]) *1000);
endTime += 3600 *hour;
endTime += 60*min;
endTime*=1000;
endTime += secmsec;
// seg[2]
int lapse = (int)(Double.parseDouble(seg[2].substring(0,seg[2].length()-1)) *1000);
startTime = endTime-lapse+1;
start[i]=startTime;
end[i] =endTime;
}
}
public static int solution(String[] lines) {
int answer = 0;
NumberFormat format = NumberFormat.getInstance();
format.setGroupingUsed(false);
int[] start = new int[lines.length];
int[] end = new int[lines.length];
set(start,end,lines);
int max = Integer.MIN_VALUE;
int curCnt=0;
for(int i=0;i<lines.length;i++){
curCnt=0;
int curCond = end[i]+1000-1;
for(int j=i;j<lines.length;j++){
if(curCond>=start[j]) curCnt++;
}
if(max<curCnt)max =curCnt;
}
answer = max;
return answer;
}
public static void main(String[] args) {
int res = solution(new String[]{
"2016-09-15 20:59:57.421 0.351s",
"2016-09-15 20:59:58.233 1.181s",
"2016-09-15 20:59:58.299 0.8s",
"2016-09-15 20:59:58.688 1.041s",
"2016-09-15 20:59:59.591 1.412s",
"2016-09-15 21:00:00.464 1.466s",
"2016-09-15 21:00:00.741 1.581s",
"2016-09-15 21:00:00.748 2.31s",
"2016-09-15 21:00:00.966 0.381s",
"2016-09-15 21:00:02.066 2.62s"
});
System.out.println(res);
}
(28분)
주어지는 로그 데이터의 형식이 2016-09-15 hh:mm:ss.sss 이기 때문에 s 단위 또는 msec 단위로 변환해야 할 것 같다. 나는 float형식에 익숙하지 않기에 정수형으로 변환하려 한다.
먼저 lines[i] 하나를 받아서 split해보자
String[] temp = lines[i].split(" ");
// temp[1]은 hh:mm:ss.sss 를 temp[2]는 T를 담고 있다.
String[] times = temp[1].split(":");
//
💥 문제를 느끼는 부분은 T가 주어지는 형식이 2s를 2.0s라고 주어지기도 하고 2.00s 로 주어지기도 한다는 것이다.
class Solution {
public int max = 0;
public void solve(int[] fin, int[] task){
int cnt =0;
// 전체 탐색
for(int i=0;i<fin.length;i++){
cnt =0;
// fin[i]+1000 - 1(i 번째 task의 완료시간을 포함하여 1sec 동안) 이 fin[j]-task[j]+1 (j번째 task의 수행시간동안 겹치는 시간이있는지를 )이상인지를 체크한다.
for(int j=i;j<fin.length;j++){
if(fin[i]+1000-1>=fin[j]-task[j]+1) cnt++;
}
if(max<cnt) max = cnt;
}
}
public int solution(String[] lines){
int answer =0;
int[] fin = new int[lines.length]; // 완료시간을 msec 단위로 저장
int[] task = new int[lines.length]; // 완료하는데 걸리는 시간을 msec단위로 저장
// 처리
String[] temp = null;
String[] times = null;
int cnt=0,i=0;
for(String line:lines){
cnt =0;
temp = line.split(" ");
times = temp[1].split(":");
cnt+=Integer.parseInt(times[0])*60*60; // 01
cnt+=Integer.parseInt(times[1])*60; // 00
cnt*=1000;
cnt += (int) (Double.parseDouble(times[2]) * 1000);
fin[i]=cnt;
task[i++] = (int) (Double.parseDouble(temp[2].split("s")[0]) * 1000);
}
solve(fin,task);
answer = max;
return answer;
}
}
정확성 테스트
테스트 1 〉 통과 (0.76ms, 69.4MB)
테스트 2 〉 통과 (11.23ms, 86.3MB)
테스트 3 〉 통과 (11.93ms, 71.2MB)
테스트 4 〉 통과 (115.80ms, 92MB)
테스트 5 〉 통과 (2.46ms, 77.8MB)
테스트 6 〉 통과 (2.24ms, 69.4MB)
테스트 7 〉 통과 (18.98ms, 86.5MB)
테스트 8 〉 통과 (12.46ms, 75MB)
테스트 9 〉 통과 (2.71ms, 73.2MB)
테스트 10 〉 통과 (0.53ms, 75.9MB)
테스트 11 〉 통과 (0.57ms, 75.9MB)
테스트 12 〉 통과 (17.76ms, 82.6MB)
테스트 13 〉 통과 (2.32ms, 71.3MB)
테스트 14 〉 통과 (0.45ms, 75.5MB)
테스트 15 〉 통과 (0.45ms, 66.5MB)
테스트 16 〉 통과 (0.74ms, 70.4MB)
테스트 17 〉 통과 (2.70ms, 79.9MB)
테스트 18 〉 통과 (21.23ms, 80.6MB)
테스트 19 〉 통과 (23.43ms, 101MB)
테스트 20 〉 통과 (15.85ms, 94.4MB)
테스트 21 〉 통과 (0.39ms, 73.4MB)
테스트 22 〉 통과 (0.40ms, 72.9MB)