Algorithm

[프로그래머스] 약수의 개수와 덧셈- Kotlin

jwkane 2024. 4. 30. 21:56

1.문제


1-1 문제 이해

두 정수가 주어지면 

left부터 right까지의 모든 수들 중 

약수의 개수가

짝수인 수는 더하고,

홀수인 수는 뺀 값을

리턴하는 함수 만들기

 

만약

left = 13

right = 17이면

13~17사이에 수들의 약수 개수가 짝수인지  홀수인지에 따라 더하고 빼면 되는 식

 

13의 약수 = 1,13 = 2개

14의 약수 = 1,2,7,14 = 4개

15의 약수 = 1,3,5,15 = 4개

16의 약수 = 1,2,4,8,16 = 5개

17의 약수 = 1,17 = 2개

이므로

 

13+14+15-16+17 =  43을 리턴하면 된다

1-2 로직구성

1. left부터 right까지의 모든 수 탐색

2. 약수의 개수 구하기

3. 약수가 짝수면 더하기, 홀수면 빼기


1-3 풀이 과정

1. left부터 right까지의 모든 수 탐색

 

특정 범위의 모든 수를 탐색하기위해 

for문을 사용했다.

class Solution {
    fun solution(left: Int, right: Int): Int {
        for(i in left..right){ // left부터 right 탐색
            }
     
    }
}

 

2. 약수의 개수 구하기

left부터 right 사이의 모든 수의 약수의 개수가짝수인지 홀수인지 아려면일단 개수가 몇개인지부터 알아야한다고 생각했다.

 

약수를 구하는 방법으로

 

반복문의각 탐색 대상 숫자와1부터 해당 수까지의 범위의 수들을 대응해 모두 나머지 연산을 시도하고 그 값이 0이면

 

그 수의 약수이므로 count 변수에 저장하고

 

그 count를 카운트리스트에 순서대로 저장해서 각 순서별 약수의 개수를 기억할 수 있도록 했다.

class Solution {
    fun solution(left: Int, right: Int): Int {
        var count = 0
        var countList = mutableListOf<Int>()
        
        for(i in left..right){ 
            for(j in 1..i){ // 각 반복의 대상 숫자와 1부터 해당 숫자까지의 범위
                if(i % j == 0){ // 나머지가 0이면 약수
                    count += 1 // 약수라면 count를 1씩 올려서 약수의 개수 파악
                }
            }
            countList += count// count를 countList에 저장하여 각 순서별 약수의 개수를 기억
            count=0 // 다음 수를 위해 다시 count 초기화
        }
        
    }
}

3. 약수가 짝수면 더하기, 홀수면 빼기

이제 countList에 담긴

각 숫자별 약수의 개수정보를 가지고

짝수면 더하고 홀수면 뺀 연산 값을

answer에 저장했다.

class Solution {
    fun solution(left: Int, right: Int): Int {
        var answer: Int = 0
        var num = 0
        var count = 0
        var even = mutableListOf<Int>()
        var countList = mutableListOf<Int>()
        
        for(i in left..right){
            for(j in 1..i){
                if(i % j == 0){
                    count += 1
                }
            }
            countList += count
            count=0
        }
        
        for(i in left..right){ // left부터 right숫자 하나씩 접근
            if(countList[num++] %2 == 0){ // 같은 인덱스를 가진 countList에 인덱스에 접근 
            				// 2로 나눈 나머지값이 0인지 확인하여 짝수 파악
                answer+=i // 짝수면 더하고
            }else{
                answer -= i // 홀수면 뺀다
            }
        }
        return answer
    }
}


 

2. 다른 문제 풀이

2-1 map활용

map을 활용하여 간결하게 푸는것도 가능했다.

map은 Collection 에 사용할 수 있는 고차 함수이다. 

Collection 을 구성하는

각 요소들에 대해 특정 표현식에 의거하여

변형을 거친 뒤 새로운 Collection 을 반환해준다

 

예를들어

list라는 Collection에 .map을 이용하여 각 요소들에 대해

곱하기 10을 

아래와 같이 할 수 있다.

fun main(){
	var a:List<Int> = listOf(1,2,3)
   	var b = a.map{it * 10}
    print(b)
}

출력 결과

[10, 20, 30]

 

2-2 filter활용

 

filter라는 고차함수는

 

이름에서 알 수 있듯 

특정 조건에 부합하는 요소만 걸러내서

새로운 Collection 을 반환해준다.

Boolean 값을 반환하는 표현식을 주입해준다.

 

filter를 이용해 짝수만 반환하고 싶다면

아래와 같이 사용할 수 있다.

fun main(){
	var a = listOf(1,2,3,4,5,6)
    var b = a.filter{if % 2 == 0}
    print(b)
}

출력 결과

[2, 4, 6]

 

이번 예제에서 (left..right)라는 Collection에 map을 통해

 

각 요소에 접근한 뒤

 

filter를 활용해

 

각 요소 % 1..해당 요소까지의 범위 = 0인 만큼 filter를 하고 / 약수를 구하고

그 약수만 남은 Collction에 size를 이용해 약수의 개수를 구하고

그 size % 2 ==0이면! map에서 접근한 요소  그대로 더하고 

아니면 해당 요소에 -부호를 붙여서

sum으로 연산한다.

class Solution {
    fun solution(left: Int, right: Int): Int {
        return (left..right).map { i -> if ((1..i).filter { i % it == 0 }.size % 2 == 0) i else -i }.sum()
    }
}