[Study] lv.1 개인정보 수집 유효기간 ( 40% )

ayboori·2023년 7월 26일
0

Java Study

목록 보기
19/34

문제 설명

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)

사용한 함수

String > Date 변환

참조
Date > String 과 마찬가지로 SimpleDateFormat 을 사용한다.

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("구분 문자") 를 사용한다.

List > int []

참조 : 이 경우 Integer 객체로 리턴되기 때문에 일일히 붙여주는 방법을 택했다.

다른 사람의 풀이 1 - 스터디원

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 이하로 훨씬 빨랐다.

다른 사람의 풀이 2 - 프로그래머스

    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;
    }

연, 월, 일을 다 더해 하나의 숫자로 만들어 비교했다.
비교 로직이 더 짧아지는 장점이 있다.

profile
프로 개발자가 되기 위해 뚜벅뚜벅.. 뚜벅초

0개의 댓글