Open In App

Check if a palindromic matrix can be formed from the given array elements

Given an array arr[] consisting of N2 integers, the task is to check whether a matrix of dimensions N * N can be formed from the given array elements, which is palindrome. If it is possible, print the palindrome matrix.

A palindrome matrix is the one in which each of the rows and columns are palindrome.



Examples:

Input: arr[] = {5, 1, 3, 4, 5, 3, 5, 4, 5}
Output:
Yes
5 3 5
4 1 4
5 3 5



Input: arr[] = {3, 4, 2, 1, 5, 6, 6, 6, 9}
Output: No

Approach: Below is some observations based on which the given problem can be solved:

Now using the Greedy Technique fill the matrix using the below steps:

  1. Use a priority queue to store the frequency of the elements in a sorted manner.
  2. If the current row is not the middle row then choose an element having a frequency of at least 4 to place these 4 numbers at symmetrically on the four corners such that the row and column in which it is placed remain palindromic.
  3. If the current row is the middle row choose an element having a frequency of at least 2 to place the values symmetrically.
  4. If at any step the required number of elements is not found then the palindrome matrix is not possible then print No
  5. Otherwise, print Yes and print the palindromic matrix formed.

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to fill the matrix to
// make it palindromic if possible
void fill(vector<pair<int, int> >& temp,
          priority_queue<pair<int, int> >& q,
          vector<vector<int> >& 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<int, int> mp;
 
    // Stores in the order of frequency
    priority_queue<pair<int, int> > q;
 
    // To store the palindromic
    // matrix if exists
    vector<vector<int> >
    grid(N, vector<int>(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<pair<int, int> > 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;
}




import java.util.*;
 
class Program {
    static void fill(List<Pair<Integer, Integer>> temp, PriorityQueue<Pair<Integer, Integer>> q, int[][] grid) {
        Pair<Integer, Integer> it = q.peek();
        q.poll();
 
        if (it.getFirst() < temp.size()) {
            System.out.println("No");
            System.exit(0);
        }
 
        for (Pair<Integer, Integer> c : temp) {
            grid = it.getSecond();
        }
 
        it.setFirst(it.getFirst() - temp.size());
        q.offer(it);
    }
 
    static void checkPalindrome(int[] A, int N) {
        Map<Integer, Integer> mp = new HashMap<>();
        PriorityQueue<Pair<Integer, Integer>> q = new PriorityQueue<>(Collections.reverseOrder(Comparator.comparing(Pair::getFirst)));
 
        int[][] grid = new int[N][N];
 
        for (int c = 0; c < N * N; c++) {
            mp.put(A, mp.getOrDefault(A, 0) + 1);
        }
 
        for (Map.Entry<Integer, Integer> entry : mp.entrySet()) {
            q.offer(new Pair<>(entry.getValue(), entry.getKey()));
        }
 
        int m = N / 2;
        List<Pair<Integer, Integer>> temp = new ArrayList<>();
 
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                int revI = N - i - 1;
                int revJ = N - j - 1;
 
                temp.addAll(Arrays.asList(
                        new Pair<>(i, j),
                        new Pair<>(revI, j),
                        new Pair<>(i, revJ),
                        new Pair<>(revI, revJ)
                ));
 
                fill(temp, q, grid);
                temp.clear();
            }
        }
 
        if (N % 2 == 1) {
            for (int i = 0; i < m; i++) {
                temp.addAll(Arrays.asList(
                        new Pair<>(i, m),
                        new Pair<>(N - i - 1, m)
                ));
 
                fill(temp, q, grid);
                temp.clear();
 
                temp.addAll(Arrays.asList(
                        new Pair<>(m, i),
                        new Pair<>(m, N - i - 1)
                ));
 
                fill(temp, q, grid);
                temp.clear();
            }
 
            temp.add(new Pair<>(m, m));
            fill(temp, q, grid);
        }
 
        System.out.println("Yes");
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                System.out.print(grid[i][j] + " ");
            }
            System.out.println();
        }
    }
 
    public static void main(String[] args) {
        int[] A = {1, 1, 1, 1, 2, 3, 3, 4, 4};
        int N = (int) Math.sqrt(A.length);
 
        checkPalindrome(A, N);
    }
}
 
class Pair<K, V> {
    private K first;
    private V second;
 
    Pair(K first, V second) {
        this.first = first;
        this.second = second;
    }
 
    K getFirst() {
        return first;
    }
 
    void setFirst(K first) {
        this.first = first;
    }
 
    V getSecond() {
        return second;
    }
 
    void setSecond(V second) {
        this.second = second;
    }
}




import math
 
def fill(temp, q, grid):
    it = q[0]
    q.pop(0)
 
    if it[0] < len(temp):
        print("No")
        exit(0)
 
    for c in temp:
        grid]] = it[1]
 
    it = (it[0] - len(temp), it[1])
    q.append(it)
 
def check_palindrome(A, N):
    mp = {}
    q = []
    grid = [[0 for _ in range(N)] for _ in range(N)]
 
    for c in range(N * N):
        mp[A] = mp.get(A, 0) + 1
 
    for key, value in mp.items():
        q.append((value, key))
 
    q.sort(reverse=True)
 
    m = N // 2
    temp = []
 
    for i in range(m):
        for j in range(m):
            rev_i = N - i - 1
            rev_j = N - j - 1
 
            temp.extend([(i, j), (rev_i, j), (i, rev_j), (rev_i, rev_j)])
 
            fill(temp, q, grid)
            temp.clear()
 
    if N % 2 == 1:
        for i in range(m):
            temp.extend([(i, m), (N - i - 1, m)])
            fill(temp, q, grid)
            temp.clear()
 
            temp.extend([(m, i), (m, N - i - 1)])
            fill(temp, q, grid)
            temp.clear()
 
        temp.append((m, m))
        fill(temp, q, grid)
 
    print("Yes")
 
    for i in range(N):
        for j in range(N):
            print(grid[i][j], end=" ")
        print()
 
if __name__ == "__main__":
    A = [1, 1, 1, 1, 2, 3, 3, 4, 4]
    N = int(math.sqrt(len(A)))
    check_palindrome(A, N)




function fill(temp, q, grid) {
    let it = q[0];
    q.shift();
 
    if (it[0] < temp.length) {
        console.log("No");
        process.exit(0);
    }
 
    for (let c of temp) {
        grid]] = it[1];
    }
 
    it = [it[0] - temp.length, it[1]];
    q.push(it);
}
 
function checkPalindrome(A, N) {
    let mp = new Map();
    let q = [];
    let grid = new Array(N).fill().map(() => new Array(N).fill(0));
 
    for (let c = 0; c < N * N; c++) {
        mp.set(A, (mp.get(A) || 0) + 1);
    }
 
    for (let [key, value] of mp) {
        q.push([value, key]);
    }
 
    q.sort((a, b) => b[0] - a[0]);
 
    let m = Math.floor(N / 2);
    let temp = [];
 
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < m; j++) {
            let revI = N - i - 1;
            let revJ = N - j - 1;
 
            temp.push([i, j], [revI, j], [i, revJ], [revI, revJ]);
 
            fill(temp, q, grid);
            temp = [];
        }
    }
 
    if (N % 2 === 1) {
        for (let i = 0; i < m; i++) {
            temp.push([i, m], [N - i - 1, m]);
            fill(temp, q, grid);
            temp = [];
 
            temp.push([m, i], [m, N - i - 1]);
            fill(temp, q, grid);
            temp = [];
        }
 
        temp.push([m, m]);
        fill(temp, q, grid);
    }
 
    console.log("Yes");
 
    for (let i = 0; i < N; i++) {
        let row = "";
        for (let j = 0; j < N; j++) {
            row += grid[i][j] + " ";
        }
        console.log(row);
    }
}
 
let A = [1, 1, 1, 1, 2, 3, 3, 4, 4];
let N = Math.floor(Math.sqrt(A.length));
checkPalindrome(A, N);

Output
Yes
1 4 1 
3 2 3 
1 4 1


Time Complexity: O(N2)
Auxiliary Space: O(N2)


Article Tags :