5 minute read

가장 큰 정사각형 찾기

  • 📝문제 설명

    • 1와 0로 채워진 표(board)가 있습니다. 표 1칸은 1 x 1 의 정사각형으로 이루어져 있습니다.
      표에서 1로 이루어진 가장 큰 정사각형을 찾아 넓이를 return 하는 solution 함수를 완성해 주세요.
      (단, 정사각형이란 축에 평행한 정사각형을 말합니다.)

    • 예를 들어

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

      가 있다면 가장 큰 정사각형은

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

      가 되며 넓이는 9가 되므로 9를 반환해 주면 됩니다.


  • ⚠️제한사항
    • 표(board)는 2차원 배열로 주어집니다.
    • 표(board)의 행(row)의 크기 : 1,000 이하의 자연수
    • 표(board)의 열(column)의 크기 : 1,000 이하의 자연수
    • 표(board)의 값은 1또는 0으로만 이루어져 있습니다.


  • 📜입출력 예

    board answer
    [[0,1,1,1],[1,1,1,1],[1,1,1,1],[0,0,1,0]] 9
    [[0,0,1,1],[1,1,1,1]] 4
    • 입출력 예 #1: 위의 예시와 같습니다.
    • 입출력 예 #2:
        | 0 | 0 | 1 | 1 |
        | 1 | 1 | 1 | 1 |  
      

      로 가장 큰 정사각형의 넓이는 4가 되므로 4를 return합니다.


  • ✏️풀이
    #include<iostream>
    #include<vector>
    #include<algorithm>

    using namespace std;

    class P11 {
    private:
        int width;
        int height;
        vector<vector<int>> table;
        int getArea(int top, int left);		// i,j가 왼쪽상단 점일때 가장 큰 정사각형 면적을 구하는 함수
        bool isSquare(int top, int left, int bottom, int right);

    public:
        P11(vector<vector<int>> table);
        int solution();		// 가장 큰 정사각형 면적 구하는 함수
    };


    P11::P11(vector<vector<int>> table)
    {
        this->table = table;
        width = table[0].size();	// 행 사이즈
        height = table.size();		// 열 사이즈
    }

    // 내부적으로 쓰고 싶은 함수이지 외부적으로 쓰려고 만든 함수가 아님.
    // 굳이 내 클래스 밖에서 이 함수를 알 필요는 없다
    // 따라서 Sub로 만들어진 함수들은 private으로 놓는 것이 정석
    int P11::getArea(int top, int left)
    {
        int maxarea = 0;
        for (int j = left; j < width; j++) {
            for (int i = top; i < height; i++) {
                if (isSquare(top, left, i, j)) {
                    int area = (i - top + 1) * (j - left + 1);
                    if (area > maxarea) {
                        maxarea = area;
                    }
                }
            }
        }

        return maxarea;
    }

    bool P11::isSquare(int top, int left, int bottom, int right)
    {
        // 가로와 세로가 똑같은지
        if ((bottom - top) != (right - left)) {
            return false;
        }
        
        // 가로와 세로가 같을 때 그 안이 모두 1로 채워져 있는지 검사
        for (int i = top; i <= bottom; i++) {
            for (int j = left; j <= right; j++) {
                if (table[i][j] != 1) {
                    return false;
                }
            }
        }

        return true;
    }

    int P11::solution()
    {
        int maxArea = 0;

        // 먼저 1로 이어진 선분을 찾고, 그 선분이 아래로 자라날 수 있는지 체크
        for (int i = 1; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int area = getArea(i, j);
                if (area > maxArea) {
                    maxArea = area;
                }
            }
        }

        return maxArea;
    }

    int main(void) {
        vector<vector<int>> table = { {0,1,1,1}, {1,1,1,1}, {1,1,1,1}, {0,0,1,0} };
        
        P11 p11(table);
        cout << p11.solution() << endl;

        return 0;
    }


확장

    #include <iostream>
    #include <vector>
    using namespace std;

    class P11
    {
    protected:
        vector<vector<int>> table;
        int width;
        int height;
        // virtual int getArea(int top, int left); 
        // P11의 solution()이 호출되는 순간 getArea()는 virtual 함수이므로 런타임에 getArea를 호출하는 객체의 getArea함수를 가져온다
        int getArea(int top, int left);
        // virtual bool isWhatIWant(int top, int left, int bottom, int right);
        bool isWhatIWant(int top, int left, int bottom, int right);
        virtual bool isCorrectSize(int top, int left, int bottom, int right); // 정사각형인지 직사각형인지 체크

    public:
        P11(vector<vector<int>> table);
        int solution();
    };
    /* // 가장 넓은 직사각형 바꾸기 미션! */
    /* P112 */
    class P112 : public P11
    {
        // getArea에서 issquare을 수정해야하므로 통채로 getArea를 오버라이드 해서 isRect이라는 함수를 새로 만든다
        // int getArea(int top, int left);
        // virtual bool isWhatIWant(int top, int left, int bottom, int right);
        virtual bool isCorrectSize(int top, int left, int bottom, int right);

    public:
        P112(vector<vector<int>> table);
        // int solution();
    };

    ////////// P11 ///////////
    P11::P11(vector<vector<int>> table)
    {
        this->table = table;
        this->width = table[0].size();
        this->height = table.size();
    }
    int P11::solution()
    {
        int maxarea = 0;
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                int area = getArea(i, j); // 이 때의 getArea는 private으로 선언한다. 내부적으로만 쓰이기 때문에 굳이 외부적으로 드러내지 않는다
                if (area > maxarea)
                {
                    maxarea = area;
                }
            }
        }
        cout << maxarea << endl;
        return maxarea;
    }
    int P11::getArea(int top, int left)
    {
        int maxarea = 0;
        for (int j = left; j < width; j++)
        {
            for (int i = top; i < height; i++)
            {
                if (isWhatIWant(top, left, i, j))
                // top left bottom right
                {
                    int area = (i - top + 1) * (j - left + 1);
                    if (area > maxarea)
                    {
                        maxarea = area;
                    }
                }
            }
        }
        return maxarea;
    }
    bool P11::isWhatIWant(int top, int left, int bottom, int right)
    {
        if (!isCorrectSize(top, left, bottom, right)) // 가로 세로 길이 다른 경우
            return false;
        for (int i = top; i <= bottom; i++)
        {
            for (int j = left; j <= right; j++)
            {
                if (table[i][j] != 1) // 그 영역이 모두 1이 아니면 무조건 false 반환
                {
                    return false;
                }
            }
        }
        return true;
    }
    bool P11::isCorrectSize(int top, int left, int bottom, int right)
    {
        if ((bottom - top) != (right - left))
            return false;
        return true;
    }

    ///////////// P112 ////////////////
    P112::P112(vector<vector<int>> table) : P11(table)
    {;}
    /*
    int P112::solution()
    {
        int maxarea = 0;
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                int area = getArea(i, j); 
                if (area > maxarea)
                {
                    maxarea = area;
                }
            }
        }
        cout << maxarea << endl;
        return maxarea;
    }
    */
    /*
    int P112::getArea(int top, int left)
    {
        int maxarea = 0;
        for (int j = left; j < width; j++)
        {
            for (int i = top; i < height; i++)
            {
                if (isRect(top, left, i, j))
                // top left bottom right
                {
                    int area = (i - top + 1) * (j - left + 1);
                    if (area > maxarea)
                    {
                        maxarea = area;
                    }
                }
            }
        }
        return maxarea;
    }
    */
    /*
    bool P112::isWhatIWant(int top, int left, int bottom, int right)
    {
        for (int i = top; i <= bottom; i++)
        {
            for (int j = left; j <= right; j++)
            {
                if (table[i][j] != 1) // 그 영역이 모두 1이 아니면 무조건 false 반환
                {
                    return false;
                }
            }
        }
        return true;
    }
    */
    bool P112::isCorrectSize(int top, int left, int bottom, int right)
    {
        return true;
    }
    int main()
    {
        P11 myp11({ {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {0, 0, 1, 0} });
        myp11.solution();

        P112 myp112({ {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {0, 0, 1, 0} });
        myp112.solution();
    }