Algorithm / 개인정보 수집 유효기간

알고리즘 코드카타

목록 보기
24/59

문제 링크

1) 문제 풀이

func solution(_ today:String, _ terms:[String], _ privacies:[String]) -> [Int] {
    
    var answer: [Int] = []
    let intToday = Int(today.split(separator: ".").joined()) ?? 0
    
    for term in terms {
        let termArr = term.split(separator: " ")
        let type = termArr[0]
        let period = Int(termArr[1]) ?? 0
        
        for (index, privacy) in privacies.enumerated() where privacy.contains(type) {
            
            let subscription = privacy.split(separator: ".")
            var year = Int(subscription[0]) ?? 0
            var month = (Int(subscription[1]) ?? 0) + period
            var date = subscription[2]
            
            if month > 12 {
                year += month % 12 == 0 ? 1 : month / 12
                month = month % 12 == 0 ? 12 : month % 12
            }
            
            date.removeLast(2)
            
            var limit: Int = 0
            
            if "\(month)".count < 2 {
                limit = Int("\(year)0\(month)\(date)") ?? 0
            } else {
                limit = Int("\(year)\(month)\(date)") ?? 0
            }
            
            if intToday >= limit {
                answer.append(index + 1)
            }
            
        }
    }
    
    return answer.sorted(by: <)
}

결과

2) 코드 개선

🚨 문제 요약

1. 약관 타입이 privacy 문자열에 포함되는지만으로 확인

for (index, privacy) in privacies.enumerated() where privacy.contains(type)
  • "A"라는 타입을 찾을 때 "AA", "AB" 같은 잘못된 매칭이 발생할 수 있음.
  • 정확히 공백으로 구분된 마지막 요소와 매칭해야 함

2. 날짜 계산 방식이 비정상

var month = (Int(subscription[1]) ?? 0) + period
  • 월 수 12를 초과할 때 처리 방식이 정확하지 않음
  • month % 12 == 0일 경우 12로 처리하는 부분은 맞지만, 이 방식은 날짜 오버플로우 처리가 부정확함
  • 예: 2022.11.02에 3개월을 더하면 2023.02.02가 되어야 함

3. 날짜 비교 방식이 문자열 결합 후 정수 반환

Int("\(year)\(month)\(date)")
  • 날짜 앞에 0을 붙이는 방식은 버그를 유발할 가능성이 높음
  • 예: 2022.1.12022101이 되어 2022.01.01과 비교가 정확히 되지 않음

4. terms를 순회하면서 privacies를 중복 검사

  • term에 대해 모든 privacies를 검사 → 불필요한 중복
  • O(n*m) 구조로, terms를 먼저 dictionary로 변환해서 매 privacy마다 매칭하는게 더욱 효율적
func solution(_ today: String, _ terms: [String], _ privacies: [String]) -> [Int] {
    // 오늘 날짜를 일 수로 변환
    func convertToDays(_ date: String) -> Int {
        let parts = date.split(separator: ".").map { Int($0)! }
        return parts[0] * 12 * 28 + parts[1] * 28 + parts[2]
    }

    let todayDays = convertToDays(today)

    // terms를 딕셔너리로 변환
    var termDict: [String: Int] = [:]
    for term in terms {
        let parts = term.split(separator: " ")
        termDict[String(parts[0])] = Int(parts[1])!
    }

    var result: [Int] = []

    for (i, privacy) in privacies.enumerated() {
        let parts = privacy.split(separator: " ")
        let date = String(parts[0])
        let type = String(parts[1])
        
        let collectedDays = convertToDays(date)
        let expireDays = collectedDays + termDict[type]! * 28

        if todayDays >= expireDays {
            result.append(i + 1)
        }
    }

    return result
}

결과

profile
이유있는 코드를 쓰자!!

0개의 댓글