[프로그래머스 [월간 코드챌린지 시즌1]] 쿼드압축 후 개수 세기- C++

level 2

Posted by dongjune on December 19, 2020

문제

쿼드압축 후 개수 세기

풀이

분할 정복을 사용하여 풀 수 있는 문제입니다.

재귀 함수를 사용하여 현재 검사하는 정사각형의 모든 수가 같지 않다면 사각형을 4등분으로 나눠서 재귀함수를 호출해줍니다.
만약 현재 검사하는 정사각형의 모든 수가 같다면 0 또는 1의 개수를 1 증가시킨 후 재귀함수를 호출하지 않고 바로 return 해줍니다.

저는 처음에 재귀함수의 인자를 다음과 같이 설정해줬는데, 시간초과가 일어났습니다.

1
2
3
void zip(int y,int x,int size,vector<vector<int>> arr){
    // ....
}

위의 코드가 왜 시간초과가 날까요?
바로 arr 벡터를 참조형으로 받지 않아서입니다. 따라서 매번 재귀함수 호출 때 마다 일일이 arr 벡터를 복사하게 돼서 시간초과가 일어나게 됩니다.
그래서 다음과 같이 arr을 참조형으로 바꿔주니 시간초과가 일어나지 않았습니다.

1
2
3
void zip(int y,int x,int size,vector<vector<int>> &arr){
    // ....
}

다음은 전체 소스 코드입니다.

소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <string>
#include <vector>

using namespace std;

int zero,one; // 0의 개수, 1의 개수

void zip(int y,int x,int size,vector<vector<int>> &arr){
    int cur = arr[y][x]; // 기준값
    
    bool flag=true; // 현재 사각형이 모두 같은수라면 true
    for(int i = y ; i < y + size ; i++){
        if(!flag) break;
        for(int j = x ; j < x+size ; j++){
            if(cur != arr[i][j]){
                flag = false;
                break;
            }
        }
    }

    // 모두 같은 수라면 0 또는 1 의 개수 증가 후 
    // 재귀 호출 하지 않고 바로 return
    if(flag){
        cur==0 ? zero++ : one++ ;
        return;
    }
    // 현재 사각형을 4등분하여 재귀함수 호출
    zip(y,x,size/2,arr);
    zip(y,x+size/2,size/2,arr);
    zip(y+size/2,x,size/2,arr);
    zip(y+size/2,x+size/2,size/2,arr);

}

vector<int> solution(vector<vector<int>> arr) {
    vector<int> answer;

    zip(0,0,arr.size(),arr);
    
    answer.assign({zero,one});
    return answer;
}