ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] CountNonDivisible 코딜리티 코딩테스트
    개발/Swift 2022. 3. 5. 18:26

    주어진 배열 값중 약수가 아닌 갯수를 세어

    배열값으로 리턴해주는 문제이다.

    A[0] = 3
        A[1] = 1
        A[2] = 2
        A[3] = 3
        A[4] = 6
    the function should return [2, 4, 3, 2, 0], as explained above.
    

    3의 약수가 아닌 2,6 ← 두개이므로 2

    1의 약수가 아닌 모든값

    2의 약수가 아닌 3,3,6 ← 3개이므로 3

    위 해답을 찾기위해 가장 단순한 방법은

    반복문을 돌려 약수인지 아닌지 조건을 걸어 카운팅후 배열에 넣어

    리턴하는 방법이다.

    public func solution(_ A : inout [Int]) -> [Int] {
        if(A.count == 1){return [0]}
        var arr = [Int]()
        var dict = [Int:Int]()
    
        func countNonDivisor(index:Int,number:Int) -> Int{
            var divisorCount = 1
            for i in 0..<A.count{
    
                if(index != i) {
                    if(number % A[i] == 0){
                        divisorCount += 1
                    }
                }
                
            }
            return A.count - divisorCount
        }
    
        for i in 0..<A.count{
            if let valueFromDict = dict[A[i]] {
                arr.append(valueFromDict)    
            }else{
                let nonDivisorCount = countNonDivisor(index:i,number:A[i])
                arr.append(nonDivisorCount)
                dict[A[i]] = nonDivisorCount
            }
           
        }
    
        return arr
    }
    

    number % A[i] == 0 이부분이 약수를 구하는 조건이다.

    다만 이미 구해진 갯수에 대해서는 countNonDivisor 함수를 타지않고

    dict에서 꺼내 사용했다.

    그러나 O(N**2) 가 적용되어 시간 초과를 했다.

    해답은 이렇다.

    제공받는 값의 범위는 1 ~ N(배열의길이)* 2 이다.

    예시는 총 5의 배열길이 이므로 1~10 사이 값이 들어올것이다.

    [3,1,2,3,6] 를 예시로 이런 배열을 만들어낸다.

    [0,1,1,2,0,0,1,0,0,0,0]

    배열의 총 길이는 10이고

    값은 값의 갯수를 의미한다. 1은1개, 2는 1개, 3은2개 ,6은 1개이다.

    이 배열의 값을 나중에 참조할것이다.

    해당 배열을 Count 라고 하자.

    // A = [3,1,2,3,6]
    var count = Array(repeating: 0, count: (2 * A.count)+1)
    var arr = [Int]()
    for i in 0..<A.count{
        count[A[i]] += 1
    }
    //[0,1,1,2,0,0,1,0,0,0,0]
    

    그리고 이제 약수가 아닌 갯수를 찾기위해 주어진 배열만큼 반복을 시킬것이다.

    처음으로 A[0] = 3 이 들어온 경우

    기존에 약수 찾기를 했던것 처럼 (이전글 참조)

    j*j ≤ 3 까지만 반복문을 돌릴것이다. (j = 1 부터 시작)

    j = 1 인경우

    3 % j == 0 의 조건이 성립한다 ⇒ 1은 3의 약수이다.

    추가로 3 / 1 (=3) 또한 3의 약수이다.

    그렇다면 여기서 Count배열을 사용한다.

    Count 배열에서 1의 갯수와 3의 갯수를 꺼내온다.

    1의 갯수 = 1 / 3의 갯수 = 2

    그러면 A 배열의 모든 수에서 3개를 뺀 2개가

    A[0] = 3 일경우의 약수가 아닌 갯수가 된다.

    public func solution(_ A : inout [Int]) -> [Int] {
        
        var count = Array(repeating: 0, count: (2 * A.count)+1)
        var arr = [Int]()
        for i in 0..<A.count{
            count[A[i]] += 1
        }
        for i in 0..<A.count{
            var divisors = 0
            var j = 1
            while j*j <= A[i] {
                if(A[i] % j == 0){
                    if(A[i] == j*j){
                        divisors += count[j]
                    }else{
                        divisors += count[j]
                        divisors += count[A[i]/j]
                    }
                }
                j += 1
            }
            arr.append(A.count - divisors)
        }
        
        return arr
    }
    

    댓글

Designed by Tistory.