📌  相关文章
📜  检查是否可以从给定的数组元素中形成回文矩阵

📅  最后修改于: 2021-04-22 00:43:13             🧑  作者: Mango

给定一个由N 2个整数组成的数组arr [] ,任务是检查是否可以从给定的数组元素(回文)中形成维度为N * N的矩阵。如果可能,请打印回文矩阵。

例子:

方法:以下是可解决给定问题的一些观察结果:

  • 这里的一个重要观察结果是–要将值放在第一行的第一列中,需要将相同的值完全放在同一行的最后一列中,以保留该行的回文行为。另外,要使列回文,必须在最后一行的第一列和最后一列中输入相同的值。
  • 因此,总共需要4个相同值的实例,以将它们对称地放入矩阵中。
  • 同样在矩阵具有奇数行和列的情况下,中间行和列仅需要两个值相同的实例,因为中间行和列中的元素将彼此对称。
  • 因此,这里的元素可以分为三种类型:
    1. 频率为4的倍数的元素。
    2. 频率为2的倍数的元素。
    3. 仅存在一次的元素。

现在,使用贪婪技术,通过以下步骤填充矩阵:

  1. 使用优先级队列以排序的方式存储元素的频率。
  2. 如果当前行不是中间行,则选择一个频率至少为4的元素,以将这4个数字对称地放置在四个角上,以使放置它的行和列保持回文。
  3. 如果当前行是中间行,则选择一个频率至少为2的元素以对称地放置这些值。
  4. 如果在任何步骤都找不到所需数量的元素,则不可能使用回文矩阵,然后打印No。
  5. 否则,打印“是”并打印形成的回文矩阵。

下面是上述方法的实现:

C++14
// C++ program for the above approach
  
#include 
using namespace std;
  
// Function to fill the matrix to
// make it palindromic if possible
void fill(vector >& temp,
          priority_queue >& q,
          vector >& grid)
{
    // First element of priority queue
    auto it = q.top();
    q.pop();
  
    // If the frequency of element is
    // less than desired frequency
    // then not possible
    if (it.first < temp.size()) {
        cout << "No\n";
        exit(0);
    }
  
    // If possible then assign value
    // to the matrix
    for (auto c : temp) {
        grid
            = it.second;
    }
  
    // Decrease the frequency
    it.first -= temp.size();
  
    // Again push inside queue
    q.push(it);
}
  
// Function to check if palindromic
// matrix of dimension N*N can be
// formed or not
void checkPalindrome(int A[], int N)
{
    // Stores the frequency
    map mp;
  
    // Stores in the order of frequency
    priority_queue > q;
  
    // To store the palindromic
    // matrix if exists
    vector >
    grid(N, vector(N));
  
    for (int c = 0; c < N * N; c++) {
  
        mp[A]++;
    }
  
    // Number of rows
  
    // Assign in priority queue
    for (auto c : mp)
        q.push({ c.second, c.first });
  
    // Middle index
    int m = N / 2;
  
    // Stores the indexes to be filled
    vector > temp;
  
    for (int i = 0; i < m; i++) {
  
        for (int j = 0; j < m; j++) {
  
            // Find the opposite indexes
            // which have same value
            int revI = N - i - 1;
            int revJ = N - j - 1;
  
            temp = { { i, j },
                     { revI, j },
                     { i, revJ },
                     { revI, revJ } };
  
            // Check if all the indexes
            // in temp can be filled
            // with same value
            fill(temp, q, grid);
  
            temp.clear();
        }
    }
  
    // If N is odd then to fill the
    // middle row and middle column
    if (N & 1) {
  
        for (int i = 0; i < m; i++) {
  
            // Fill the temp
            temp = { { i, m },
                     { N - i - 1, m } };
  
            // Fill grid with temp
            fill(temp, q, grid);
  
            // Clear temp
            temp.clear();
  
            // Fill the temp
            temp = { { m, i },
                     { m, N - i - 1 } };
  
            // Fill grid with temp
            fill(temp, q, grid);
            temp.clear();
        }
  
        // For the middle element
        // of middle row and column
        temp = { { m, m } };
        fill(temp, q, grid);
    }
  
    cout << "Yes" << endl;
  
    // Print the matrix
    for (int i = 0; i < N; i++) {
  
        for (int j = 0; j < N; j++) {
  
            cout << grid[i][j] << " ";
        }
        cout << endl;
    }
}
  
// Driver Code
int main()
{
    // Given array A[]
    int A[] = { 1, 1, 1, 1, 2, 3, 3, 4, 4 };
  
    int N = sizeof(A) / sizeof(A[0]);
  
    N = sqrt(N);
  
    // Function call
    checkPalindrome(A, N);
  
    return 0;
}


输出:
Yes
1 4 1 
3 2 3 
1 4 1

时间复杂度: O(N 2 )
辅助空间: O(N 2 )