본문 바로가기

Problem Solving/백준

[Kotlin] 코틀린 중복된 횟수 구하기

기존에는 C++ 만 사용했는데 컬렉션을 잘만 활용한다면 코틀린이 정말 편한것 같다.

그러나 여전히 모든걸 스트링으로 읽어와야한다는것,,, 아직 불편하다. 입력받거나 배열 생성해주는건 아직까지 C++ 이 더 익숙하다.

코틀린으로 할때마다 매번 찾아봐서 안까먹기 위해 정리한다.

 

코틀린 컬렉션 활용하기

GropuBy

IntArray.groupBy를 살펴보면 다음과 같다.

public inline fun <K> IntArray.groupBy(keySelector: (Int) -> K): Map<K, List<Int>> {
    return groupByTo(LinkedHashMap<K, MutableList<Int>>(), keySelector)
}

 

주어진 keySelector function이 돌려주는 값들을 key값으로 하고 key값과 매칭되는 원소들을 list로 가지는 맵을 돌려준다.

 

그러면 groupByTo는 뭘 하는 애일까?

public inline fun <K, M : MutableMap<in K, MutableList<Int>>> IntArray.groupByTo(destination: M, keySelector: (Int) -> K): M {
    for (element in this) {
        val key = keySelector(element)
        val list = destination.getOrPut(key) { ArrayList<Int>() }
        list.add(element)
    }
    return destination
}

 

 

각 원소를 돌면서 키값에 해당되는 원소들을 넣어준다.

 

처음에는 groupBy를 생각했는데 List 타입인 경우에 더 짱인것을 찾았다.

만일 array 형식 이라면 .toList()를 이용해 리스트로 바꿔준후에 다음을 사용하면 된다.

GroupingBy

nums.groupingBy { it }.eachCount()

이렇게 하면 다음의 값들이 이렇게 바뀐다.

nums = listOf( -1, -2, -3, -1, -2)

mapOf<Int, Int>(
	-1 to 2
	-2 to 2
	-3 to 1
)

연관 문제

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

처음 짠 코드

최빈값을 구하는 부분에서 고민을 많이 했는데 groupBy를 살펴보고 나니,, 이렇게 비효율적으로 짰을수가!

import kotlin.math.roundToInt

fun getIntInput() = readLine()!!.trim().toInt()
fun getInputList() = readLine()!!.trim().split(' ')
fun getMid(n: Int): Int = n/2

fun main() {
    with(System.`in`.bufferedReader()) {
        val N = getIntInput()
        var sum = 0L
        var frequency: Int
        var min: Int
        var max: Int

        val nums = IntArray(N) {
            getIntInput().also{
                sum+= it.toLong()
            }
        }.also {
            min = it.minOf { it }
            max = it.maxOf { it }
        }
        println((sum.toDouble()/N.toDouble()).roundToInt())
        println(nums.sortedArray().get(getMid(N)))
        nums.groupBy { it }.map {
            it.key to it.value.size
        }.sortedWith( compareBy<Pair<Int, Int>> {it.second}.thenByDescending{it.first})
        .let {
            countedNums ->
            if(countedNums.count { it.second == countedNums.last().second } > 1){
                println(countedNums[countedNums.size-2].first)
            } else println(countedNums.last().first)
        }
        println(max-min)


    }
}

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 1966: 프린터큐  (0) 2021.02.26
[백준] 1406번: 에디터  (0) 2021.02.24
[백준] 9012: 괄호  (0) 2021.02.24
[백준] 10816: 숫자 카드 2  (0) 2021.02.24
[백준] 11651번 : 좌표 정렬하기 2  (0) 2021.02.24