כיכר מקסימלית  


רמת קושי בינוני
נשאל לעתים קרובות Adobe אמזון בעברית AppDynamics תפוח עץ פייסבוק Google יבמ פייפאל טויטר
מערך תכנות דינמי מַטרִיצָה

בבעיית המרובע המרבי נתנו בינארי דו-ממדי מַטרִיצָה מלא 0 ו -1, מצא את הריבוע הגדול ביותר המכיל 1 בלבד והחזיר את שטחו.

דוגמה  

קלט:

1 0 1 0 0

0 0 1 1 1

1 1 1 1 1

0 0 0 1 0

פלט:

4

גישת כוח הברוט  

הדרך הכוחנית לפתור בעיה זו היא לחזור על כל תת המטריצה ​​המרובעת האפשרית ולבחור את המקסימום מתוכן.

תוכנית C ++ לריבוע מרבי

#include <bits/stdc++.h>
using namespace std;
int maximalSquare(vector<vector<char>> &matrix)
{
    int answer = 0;
    int n = matrix.size();
    if (n == 0)
    {
        return 0;
    }
    int m = matrix[0].size();
    if (m == 0)
    {
        return 0;
    }
    for (int sidelength = 1; sidelength <= min(n, m); sidelength++) // sidelength denotes the side length of the sub-matrix
    {
        // i,j are the top left index of the current sub-matrix
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if ((i + sidelength > n) or (j + sidelength > m)) //check if the current sub-matrix is not out of bounds
                {
                    continue;
                }
                bool zero = false;
                // check if this sub matrix contain any zero or not
                for (int x = i; x < i + sidelength; x++)
                {
                    for (int y = j; y < j + sidelength; y++)
                    {
                        if (matrix[x][y] == '0')
                        {
                            zero = true;
                        }
                    }
                }
                if (zero == false) // if this does not contain any zero than this is a valid sub matrix
                {
                    answer = max(answer, sidelength * sidelength);
                }
            }
        }
    }
    return answer;
}
int main()
{
    int n, m;
    cin >> n >> m;
    vector<vector<char>> matrix(n, vector<char>(m));
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> matrix[i][j];
        }
    }
    int answer = maximalSquare(matrix);
    cout << answer << endl;
    return 0;
}
4 4
1 0 1 0 
1 0 1 1 
1 1 1 1 
1 0 0 1 
4

תוכנית JAVA לריבוע מקסימלי

import java.util.*;
public class Main
{
    public static int maximalSquare(char[][] matrix)
    {
        int answer = 0;
        int n = matrix.length;
        if (n == 0)
        {
            return 0;
        }
        int m = matrix[0].length;
        if (m == 0)
        {
            return 0;
        }
        for (int sidelength = 1; sidelength <= Math.min(n, m); sidelength++) // sidelength denotes the side length of the sub-matrix
        {
            // i,j are the top left index of the current sub-matrix
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    if ((i + sidelength > n) || (j + sidelength > m)) //check if the current sub-matrix is not out of bounds
                    {
                        continue;
                    }
                    boolean zero = false;
                    // check if this sub matrix contain any zero or not
                    for (int x = i; x < i + sidelength; x++)
                    {
                        for (int y = j; y < j + sidelength; y++)
                        {
                            if (matrix[x][y] == '0')
                            {
                                zero = true;
                            }
                        }
                    }
                    if (zero == false) // if this does not contain any zero than this is a valid sub matrix
                    {
                        answer = Math.max(answer, sidelength * sidelength);
                    }
                }
            }
        }
        return answer;
    }
  public static void main(String[] args) {
      Scanner sc = new Scanner(System.in);
      int n = sc.nextInt();
      int m = sc.nextInt();;
        char[][] matrix = new char[n][m];
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                matrix[i][j] = sc.next().charAt(0);
            }
        }
        int answer = maximalSquare(matrix);
    System.out.println(answer);
  }
}



4 5
1 0 1 1 1
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
9

ניתוח מורכבות

מורכבות זמן

כאשר אנו חוזרים על כל הריבועים ויהיו בערך N ^ 2 ריבועים כך שמורכבות הזמן הכוללת היא O (N ^ 4).

ראה גם
הסר את פתרונות ה- Leetcode של רשימת קישורים

מורכבות חלל

מכיוון שלא השתמשנו במרחב נוסף, כך מורכבות החלל היא O (1).

גישת תכנות דינמית  

הסבר

נניח שיש לנו DP מערך בגודל (n + 1, m + 1) כאשר dp [i] [j] מייצג את אורך הצד הגדול ביותר של ריבוע מכל אלה שהפינה השמאלית העליונה שלהם היא I, j.

אז אם מטריצה ​​[i] [j] היא אחת ממה שאנחנו יכולים לומר dp ​​[i] [j] = 1 + min (dp [i-1], dp [i] [j-1], dp [i-1 ] [j-1]) כי הריבוע הגדול ביותר של אלה עם הפינה השמאלית העליונה I, j הוא רק צומת של הריבועים הגדולים ביותר של אלה עם הפינה השמאלית העליונה (i-1, j), (I, j-1), ( i-1, j-1).

אַלגוֹרִיתְם

  1. אתחל מערך dp בגודל (n + 1, m + 1) עם אפסים.
  2. אתחל מספר שלם ועם עם אפס.
  3. חזר על כל תאי המטריצה.
    1. אם מטריצה ​​[i] [j] היא אחת מהעדכון dp [i] [j] = 1 + דקה (dp [i-1], dp [i] [j-1], dp [i-1] [j- 1]).
    2. עדכן ans = max (ans, dp [i] [j]).
  4. תשוב תשובה.

לדוגמה:

Matrix[][]={{‘1’, ‘0’, ‘1’, ‘0’, ‘0’},

{'1', '0', '1', '1', '1'},

{'1', '1', '1', '1', '1'},

{'1', '0', '0', '1', '0'}}

עבור מטריצה ​​זו, מערך dp [] [] שנראה כך:

כיכר מקסימליתאורן

dp [i] [j] מציין את אורך הצד של הריבוע המרבי של אלה שבפינה השמאלית העליונה שלהם מופיע האינדקס (i, j).

תוכנית C ++ לריבוע מרבי

#include <bits/stdc++.h>
using namespace std;
int maximalSquare(vector<vector<char>> &matrix)
{
    int n = matrix.size();
    if (n == 0)
    {
        return 0;
    }
    int m = matrix[0].size();
    if (m == 0)
    {
        return 0;
    }
    int ans = 0;
    vector<vector<int>> dp(n, vector<int>(m, 0));
    for (int i = n - 1; i >= 0; i--)
    {
        if (matrix[i][m - 1] == '1')
        {
            dp[i][m - 1]++;
            ans = 1;
        }
    }
    for (int i = m - 1; i >= 0; i--)
    {
        if (matrix[n - 1][i] == '1')
        {
            dp[n - 1][i]++;
            ans = 1;
        }
    }
    for (int i = n - 2; i >= 0; i--)
    {
        for (int j = m - 2; j >= 0; j--)
        {
            if (matrix[i][j] == '1')
            {
                dp[i][j] = min(dp[i + 1][j + 1], min(dp[i + 1][j], dp[i][j + 1])) + 1;
                ans = max(ans, dp[i][j]);
            }
        }
    }
    return ans * ans;
}
int main()
{
    int n, m;
    cin >> n >> m;
    vector<vector<char>> matrix(n, vector<char>(m));
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> matrix[i][j];
        }
    }
    int answer = maximalSquare(matrix);
    cout << answer << endl;
    return 0;
}
4 2
1 0 
1 1 
1 1
1 0
4

תוכנית JAVA לריבוע מקסימלי

import java.util.*;
public class Main
{
    public static int maximalSquare(char[][] matrix)
    {
        int n = matrix.length;
        if (n == 0)
        {
            return 0;
        }
        int m = matrix[0].length;
        if (m == 0)
        {
            return 0;
        }
        int ans = 0;
        int[][] dp = new int[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                dp[i][j]=0;
            }
        }
        for (int i = n - 1; i >= 0; i--)
        {
            if (matrix[i][m - 1] == '1')
            {
                dp[i][m - 1]++;
                ans = 1;
            }
        }
        for (int i = m - 1; i >= 0; i--)
        {
            if (matrix[n - 1][i] == '1')
            {
                dp[n - 1][i]++;
                ans = 1;
            }
        }
        for (int i = n - 2; i >= 0; i--)
        {
            for (int j = m - 2; j >= 0; j--)
            {
                if (matrix[i][j] == '1')
                {
                    dp[i][j] = Math.min(dp[i + 1][j + 1], Math.min(dp[i + 1][j], dp[i][j + 1])) + 1;
                    ans = Math.max(ans, dp[i][j]);
                }
            }
        }
        return ans * ans;
    }

  public static void main(String[] args) {
      Scanner sc = new Scanner(System.in);
      int n = sc.nextInt();
      int m = sc.nextInt();;
        char[][] matrix = new char[n][m];
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                matrix[i][j] = sc.next().charAt(0);
            }
        }
        int answer = maximalSquare(matrix);
    System.out.println(answer);
  }
}
4 5
0 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 1 1 1 1
16

ניתוח מורכבות

מורכבות זמן

כאשר אנו חוזרים על המטריצה ​​רק פעם אחת כך מורכבות הזמן היא O (N ^ 2).

ראה גם
מחק את אותן מילים רצופות ברצף

מורכבות חלל

לקחנו מערך dp בגודל (n + 1, m + 1) כך שמורכבות החלל היא O (N ^ N).

הפניות