반응형

백준 1620번 문제입니다. (solved.ac) 기준 실버 4 문제입니다.

https://www.acmicpc.net/problem/1620

 

1620번: 나는야 포켓몬 마스터 이다솜

첫째 줄에는 도감에 수록되어 있는 포켓몬의 개수 N이랑 내가 맞춰야 하는 문제의 개수 M이 주어져. N과 M은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수인데, 자연수가 뭔지는 알지? 모르면

www.acmicpc.net

문제

문제 접근

문자열을 정수로 변환할 수 있는지 확인하는, 문자열이 정수로만 구성되어있는지 확인하는 isNum()이라는 함수를 직접 만들어서 사용했는데... 코틀린의 isDigit()이라는 함수로 해당 문자열이 정수인지 아닌지 판단할 수 있습니다! 즉 isNum()은 굳이... 필요가 없는 함수입니다.

isNum()함수의 간단한 로직

 

 처음에는 mutableList를 사용하여 인덱스는 포켓몬 번호, 값에 포켓몬 이름이 들어가게 하여 간편하게 풀려고했는데 해시 문제라서 역시나 시간초과가 발생했습니다. 사실 이 방법은 당연히 시간초과가 발생할 것이라고 예상했습니다.

 

 두 번째로는 하나의 mutableMap을 만들어 키로 이름을, 값으로 번호를 저장하도록 도감을 만들었다.

퀴즈에서 입력받은 값이 이름(문자열)이라면 이름이 키기때문에 mutableMap의 get함수를 이용하여 값(번호)을 찾도록 하였고

입력받은 값이 번호(정수)라면 mutableMap의 filterValues를 사용하여 입력받은 번호를 키준으로 필터링한 후 해당 키를 joinToString()을 사용하여 문자열(포켓몬 이름)로 반환하였습니다. 

이러한 과정에서는 아마 filterValues를 사용하는 부분에서 시간초과 오류가 발생한 것 같습니다.

 

정답처리된 방법인 세 번째 방법은 이름을 키로하고 번호를 값으로 하는 도감을 하나(Map) 번호를 키로하고 이름을 값으로 가지는 도감(Map)을 하나, 총 2개의 맵을 만들어서 별도의 필터링과정을 거치지 않고 퀴즈에서 이름이 들어왔다면 이름을 키로 하는 도감에서 찾고 번호가 들어왔다면 번호를 키로하는 도감에서 해당하는 값을 찾아 정답을 반환하도록 하였습니다. 첫 번째와 두 번째 과정에서는 퀴즈에서 입력된 값인 input이 정수인지 판별하기위하여 직접만든 isNum()을 사용하였는데 코틀린의 isDigit()이라는 함수가 있다는 것을 알게되고 isNum()함수대신 isDigit()을 사용하였습니다. 어차피 입력받은 문자열의 맨 첫 번째 값이 문자면 전부다 문자이고 첫 번째 값이 정수면 전부다 정수이므로 input[0]에서 isDigit()을 판별하였습니다.

 

정답 코드

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter

fun main() {

    // 빠른 입출력
    val br = BufferedReader(InputStreamReader(System.`in`))
    val bw = BufferedWriter(OutputStreamWriter(System.out))

    // 입력받을 데이터의 개수, 퀴즈의 개수
    val (cntData, cntQuiz) = br.readLine().split(" ").map { it.toInt() }

    // 키는 포켓몬의 이름, 값은 포켓몬의 번호로 저장될 도감(Map)
    val pocketmonBookForName = mutableMapOf<String, Int>()
    // 키는 포켓몬의 번호, 값은 포켓몬의 이름으로 저장될 도감(Map)
    val pocketmonBookForNum = mutableMapOf<Int, String>()

    repeat(cntData) { index ->

        // 포켓몬의 이름
        val name = br.readLine()
        // 포켓몬의 이름이 키, 값은 포켓몬의 번호인 도감
        pocketmonBookForName.put(name, index + 1)
        // 포켓몬의 번호가 키, 값은 포켓몬의 이름인 도감
        pocketmonBookForNum.put(index + 1, name)
    }

    repeat(cntQuiz) {

        val input = br.readLine()

        // 입력으로 숫자가 들어왔다면
        if (input[0].isDigit()) {
            // 번호가 키인 도감에서 이름을 탐색
            bw.write("${pocketmonBookForNum.get(input.toInt())}\n")
            // 입력으로 문자(포켓몬의 이름이 들어왔다면
        } else {
            // 이름이 키인 도감에서 번호를 탐색
            bw.write("${pocketmonBookForName.get(input)}\n")
        }

    }

    bw.flush()
    bw.close()
}

처음 제출한  코드 - mutableList 사용 == 시간초과...

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter

fun main() {

    val br = BufferedReader(InputStreamReader(System.`in`))
    val bw = BufferedWriter(OutputStreamWriter(System.out))

    val (cntData, cntQuiz) = br.readLine().split(" ").map { it.toInt() }

    val pocketmonBook = mutableListOf<String>()

    // 인덱스 0은 미리 삽입
    pocketmonBook.add("Zero is empty ")

    repeat(cntData) {
        pocketmonBook.add(br.readLine())
    }

    repeat(cntQuiz) {
        val input = br.readLine()

        // 입력으로 숫자가 들어왔다면
        if (isNum(input)) {
            bw.write("${pocketmonBook[input.toInt()]}\n")
            // 입력으로 문자(포켓몬의 이름이 들어왔다면
        } else {
            bw.write("${pocketmonBook.indexOfFirst { it == input }}\n")
        }

    }

    bw.flush()
    bw.close()
}

// 입력받은 문자열이 정수인지 확인하는 함수
fun isNum(string: String): Boolean {

    // 입력받은 문자열이 정수라면 isNum은 true
    var isNum = true

    // 입력받은 문자열을 문자 하나씩 탐색
    string.forEach { char ->

        // 아스키코드로 변환된 "문자" - 대문자일수도 있으니 소문자로 바꿔줌.
        val charConvertedToCode = char.code

        // 정수 0의 아스키 코드는 48, 정수 9의 아스키 코드는 57 - 해당 범위를 벗어나면 정수가 아님.
        if (charConvertedToCode > 57 || charConvertedToCode < 48) {
            isNum = false
            return isNum
        }
    }

    return isNum
}

두 번째 제출한 코드 - mutableMap 1개 사용 == 시간초과

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter

fun main() {

    val br = BufferedReader(InputStreamReader(System.`in`))
    val bw = BufferedWriter(OutputStreamWriter(System.out))

    val (cntData, cntQuiz) = br.readLine().split(" ").map { it.toInt() }

    val pocketmonBook = mutableMapOf<String, Int>()

    repeat(cntData) { index ->
        // 포켓몬의 이름이 키, 값은 포켓몬의 번호(순서이자 인덱스)
        pocketmonBook.put(br.readLine(), index + 1)
    }

    repeat(cntQuiz) {
        val input = br.readLine()

        // 입력으로 숫자가 들어왔다면
        if (isNum(input)) {
            bw.write("${pocketmonBook.filterValues { it == input.toInt() }.keys.joinToString()}\n")
            // 입력으로 문자(포켓몬의 이름이 들어왔다면
        } else {
            bw.write("${pocketmonBook.get(input)}\n")
        }

    }

    bw.flush()
    bw.close()
}

// 입력받은 문자열이 정수인지 확인하는 함수
fun isNum(string: String): Boolean {

    // 입력받은 문자열이 정수라면 isNum은 true
    var isNum = true

    // 입력받은 문자열을 문자 하나씩 탐색
    string.forEach { char ->

        // 아스키코드로 변환된 "문자" - 대문자일수도 있으니 소문자로 바꿔줌.
        val charConvertedToCode = char.code

        // 정수 0의 아스키 코드는 48, 정수 9의 아스키 코드는 57 - 해당 범위를 벗어나면 정수가 아님.
        if (charConvertedToCode > 57 || charConvertedToCode < 48) {
            isNum = false
            return isNum
        }
    }

    return isNum
}
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기