https://school.programmers.co.kr/learn/courses/30/lessons/150370
수집된 개인정보가 있다.
개인정보마다 약관이 다르며 약관마다 보관기간이 다르다.
수집된 개인정보의 수집 일자, 약관 종류, 약관의 유효기간, 오늘 날짜가 주어져 있을 때
오늘 날짜로 파기해야 할 개인정보를 구해야 한다.
1. 입력 받은 오늘 날짜 String 데이터 > Date 형식으로 변환
2. 입력 받은 privacies 날짜, 약관으로 분리 / 날짜 > Date로 변환
3. 입력 받은 약관, 해당 날짜 비교해서 만료일자 설정
4. 오늘 날짜, 만료 날짜 비교
5. 만료되지 않았을 시 (비교 후 오늘 날짜보다 만료 날짜가 작거나 같을 때) List에 추가
6. ArrayList<Integer>를 int[]로 변환 후 리턴
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
class Solution {
public int[] solution(String today, String[] terms, String[] privacies) throws ParseException {
// 입력 받은 오늘 날짜 String 데이터 > Date 형식으로 변환
SimpleDateFormat transFormat = new SimpleDateFormat("yyyy.MM.dd");
Date todayDate = transFormat.parse(today);
Date inputArr [] = new Date[privacies.length];
char[] inputTermsArr = new char[privacies.length];
Calendar calendar = Calendar.getInstance();
ArrayList<Integer> ans = new ArrayList<>();
for (int i = 0 ; i < privacies.length ; i++){
// 입력 받은 privacies 날짜, 약관으로 분리 / 날짜 > Date로 변환
String[] temp = privacies[i].split(" ");
inputArr[i] = transFormat.parse(temp[0]);
calendar.setTime(inputArr[i]);
// 입력 받은 약관, 해당 날짜 비교해서 만료일자 설정
for (String a : terms) {
String[] temp2 = a.split(" ");
if (temp2[0].equals(temp[1])) {
calendar.add(Calendar.MONTH, Integer.parseInt(temp2[1]));
Date expireDate = calendar.getTime();
// 오늘 날짜, 만료 날짜 비교
if( todayDate.compareTo(expireDate) >= 0){ // 만료 X 시
ans.add(i+1);
}
continue;
}
}
}
// ArrayList<Integer>를 int[]로 변환
int[] result = new int[ans.size()];
for (int i = 0; i < ans.size(); i++) {
result[i] = ans.get(i);
}
return result;
}
}
32.99ms ~ 106.18ms
이중 for문의 사용, Date 함수 사용 때문에 길어진 게 아닐까…? 추측
테스트 1 〉 | 통과 (49.99ms, 77.8MB) |
---|---|
테스트 2 〉 | 통과 (74.96ms, 80.9MB) |
테스트 3 〉 | 통과 (106.18ms, 82.7MB) |
테스트 4 〉 | 통과 (32.99ms, 81.3MB) |
테스트 5 〉 | 통과 (34.86ms, 71.8MB) |
테스트 6 〉 | 통과 (29.07ms, 79.5MB) |
테스트 7 〉 | 통과 (41.56ms, 82.4MB) |
테스트 8 〉 | 통과 (56.29ms, 86MB) |
테스트 9 〉 | 통과 (42.02ms, 84.5MB) |
테스트 10 〉 | 통과 (45.14ms, 91.3MB) |
테스트 11 〉 | 통과 (34.02ms, 91.1MB) |
테스트 12 〉 | 통과 (67.32ms, 77.4MB) |
테스트 13 〉 | 통과 (81.40ms, 82.9MB) |
테스트 14 〉 | 통과 (36.01ms, 80.4MB) |
테스트 15 〉 | 통과 (100.76ms, 77.6MB) |
테스트 16 〉 | 통과 (70.67ms, 71.4MB) |
테스트 17 〉 | 통과 (46.34ms, 89.7MB) |
테스트 18 〉 | 통과 (50.68ms, 78.3MB) |
테스트 19 〉 | 통과 (49.13ms, 93.1MB) |
테스트 20 〉 | 통과 (46.48ms, 80.4MB) |
참조
Date > String 과 마찬가지로 SimpleDateFormat
을 사용한다.
// 문자열
String dateStr = "2021년 06월 19일 21시 05분 07초";
// 포맷터
SimpleDateFormat formatter = new SimpleDateFormat("yyyy년 MM월 dd일 HH시 mm분 ss초");
// 문자열 -> Date
Date date = formatter.parse(dateStr);
Date
형식으로는 연산이 불가 하기 때문에 Calendar
을 사용해야 한다고 한다.
이때 return 값이 Calendar 이기 때문에 calendat.getTime()
을 사용하여 다시 Date로 변환해줘야 한다.
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.DATE, 6); // 일 계산
cal1.add(Calendar.MONTH, 4); // 월 연산
cal1.add(Calendar.DATE, -3); // 빼고 싶다면 음수 입력
Date expireDate = cal1.getTime();
date.compareTo(comparedate)
를 사용한다.
값이 0일 경우 동일한 날짜, 음수일 경우 date < comparedate (이전 날짜), 양수의 경우 이후 날자다
우리의 친구 string.spit("구분 문자")
를 사용한다.
참조 : 이 경우 Integer 객체로 리턴되기 때문에 일일히 붙여주는 방법을 택했다.
public int[] solution(String today, String[] terms, String[] privacies) {
List<Integer> answerList = new ArrayList<>();
// 오늘 연도 vs, 오늘 월 vs, 오늘 일자
int todayYear = Integer.parseInt(today.substring(0, 4));
int todayMonth = Integer.parseInt(today.substring(5, 7));
int todayDay = Integer.parseInt(today.substring(8));
// 약관에 따른 유효기간 미리 Map에 저장
Map<Character, Integer> termsMap = new HashMap<>();
for (int i = 0; i < terms.length; i++) {
termsMap.put(terms[i].charAt(0), Integer.parseInt(terms[i].substring(2)));
}
// 유효기간 >= 오늘이면 보관, 유효기간 < 오늘이면 파기
for (int i = 0; i < privacies.length; i++) {
//privacies 날짜 int로 파싱하기
int year = Integer.parseInt(privacies[i].substring(0, 4));
int month = Integer.parseInt(privacies[i].substring(5, 7));
int day = Integer.parseInt(privacies[i].substring(8, 10));
// 유효기간 구하기
month += termsMap.get(privacies[i].charAt(11));
if (day == 1) {
day = 28;
month -= 1;
} else {
day -= 1;
}
if (month > 12) {
year += month / 12;
month = month % 12;
}
// 오늘과 유효기간 비교
// 유효기간보다 현재가 크면 add하고 다음 for문
// 적으면 바로 다음 for문 / 같으면 다음 비교인자에서 비교
if (year < todayYear) {
answerList.add(i + 1);
continue;
} else if (year > todayYear) {
continue;
}
if (month < todayMonth) {
answerList.add(i + 1);
continue;
} else if (month > todayMonth) {
continue;
}
if (day < todayDay) {
answerList.add(i + 1);
}
}
// list 배열로 변환하여 return
int[] answer = new int[answerList.size()];
for (int i = 0; i < answer.length; i++) {
answer[i] = answerList.get(i);
}
return answer;
}
날짜 값을 숫자로 만들어서 연, 월, 일을 비교한다.
이때 큰 단위부터 비교해서 크기가 결정되면 다음 단위는 비교할 필요가 없다.
이런 식의 로직에 경우에만 한 달은 28일로 한다
의 전제 조건이 활용될 것 같다.
실행 시간이 1ms 이하로 훨씬 빨랐다.
public int[] solution(String today, String[] terms, String[] privacies) {
List<Integer> answer = new ArrayList<>();
Map<String, Integer> termMap = new HashMap<>();
int date = getDate(today);
for (String s : terms) {
String[] term = s.split(" ");
termMap.put(term[0], Integer.parseInt(term[1]));
}
for (int i = 0; i < privacies.length; i++) {
String[] privacy = privacies[i].split(" ");
if (getDate(privacy[0]) + (termMap.get(privacy[1]) * 28) <= date) {
answer.add(i + 1);
}
}
return answer.stream().mapToInt(integer -> integer).toArray();
}
private int getDate(String today) {
String[] date = today.split("\\.");
int year = Integer.parseInt(date[0]);
int month = Integer.parseInt(date[1]);
int day = Integer.parseInt(date[2]);
return (year * 12 * 28) + (month * 28) + day;
}
연, 월, 일을 다 더해 하나의 숫자로 만들어 비교했다.
비교 로직이 더 짧아지는 장점이 있다.