Coding Test/프로그래머스

★[200706] 가장 큰 정사각형 찾기 - 연습문제(level2)

csmoon1010 2020. 7. 6. 01:04

이 문제는 기말고사 이전에 풀었던 문제지만 그 때 정리를 하지 못해서 뒤늦게 정리해본다.

programmers.co.kr/learn/courses/30/lessons/12905

 

코딩테스트 연습 - 가장 큰 정사각형 찾기

[[0,1,1,1],[1,1,1,1],[1,1,1,1],[0,0,1,0]] 9

programmers.co.kr

1. 문제 이해

- 0과 1로 이루어진 직사각형 표(2차원 배열 board로 주어짐)

- 1로 이루어진 가장 큰 정사각형 찾아 넓이를 return!!

 

2. 전략

Dynamic Programming(동적계획법) : 이전 단계의 최대값(최적의 답)을 다음 단계에서 활용

0 1 1 1
1 1 1 1
1 1 1 1
0 0 1 0

- board[0, 0]부터 시작해서 행우선으로 탐색

- i와 j가 1이상이고 만약 board[i, j] 값이 1이라면...

      board[i, j] 값 = board[i-1, j], board[i, j-1], board[i-1, j-1]의 값 중 최소값 + 1 [단, 최소값이 0보다 클 때]

→ 만들 수 있는 정사각형의 최대값(max)을 갱신!!(아래 그림 참고)

0 1 1 1
1 1 2 2
1 2 2 3
0 0 1 0

- max * max를 return!!

 

3. 참고사항

- 이전 풀이 : getMaxRec 함수를 이용

board[x, y]를 시작점(가장 왼쪽 끝)으로 한 정사각형의 변 길이를 size(초기값 1)로 하여 계산

이 중에서 max값을 return

→ (문제점) 시간이 너무 오래걸려 효율성의 문제 발생!!

- 시작점이 아닌 끝점으로 지정하여 이전 계산 결과를 이용할 수 있는 발상이 필요!!!

 

4. 코드

class Solution
{
    public int solution(int [][]board)
    {
        int answer = 0;
        int row = board.length;
        int column = board[0].length;
        int sx = 0, sy =0;
        int max = 0;
        if(board[0][0] == 1)    max=1;
        for(int i = 1; i < row; i++){
            for(int j =1;j< column; j++){
                /*if(board[i][j] == 1){
                    sx = i; sy = j;
                    max = Math.max(max, getMaxRec(sx,sy,board,row,column));
                }*///효율성 문제 발생
                if(board[i][j] == 1){
                    int min = Math.min(board[i-1][j], Math.min(board[i][j-1], board[i-1][j-1]));
                    if(min > 0) board[i][j] = min+1;
                    max = Math.max(max, board[i][j]);
                }
            }
        }
        answer = max*max;
        return answer;
    }
    
    //효율성 떨어지는 함수 getMaxRec
    public int getMaxRec(int x, int y, int[][] board, int row, int column, int max){
        int size = 1; //실제 길이는 2
        boolean check = true;
        while(x+size < row && y+size < column){
            for(int i = x; i < x+size; i++){
                if(board[i][y+size] != 1){
                    check = false; break;
                }
            }
            for(int i = y; i < y+size; i++){
                if(board[x+size][i] != 1){
                    check = false; break;
                }
            }
            if(board[x+size][y+size] !=1)   check=false;
            if(check)   size++;
            else    break;
        }
        return size;
    }
}