Open In App

Minimum steps to convert all paths in matrix from top left to bottom right as palindromic paths

Given a matrix mat[][] with N rows and M columns. The task is to find the minimum number of changes required in the matrix such that every path from top left to bottom right is a palindromic path. In a path only right and bottom movements are allowed from one cell to another cell.
Examples:

Input: mat[][] = {{1, 2}, {3, 1}} 
Output:
Explanation: 
Every path in the matrix from top left to bottom right is palindromic. 
Paths => {1, 2, 1}, {1, 3, 1}
Input: mat[][] = {{1, 2}, {3, 5}} 
Output:
Explanation: 
Only one change is required for the every path to be palindromic. 
That is => mat[1][1] = 1 
Paths => {1, 2, 1}, {1, 3, 1}

Simple Approach: 

The key observation in the problem is that elements at the same distance from the front end or rear end are equal. Therefore, find all the elements at equal distance from (0, 0) and (N-1, M-1) and then make all of them equal in a minimum number of changes. Maintain a count variable to get the total number of changes. Below is the illustration of the approach: 

Below is the implementation of the above approach: 




// C++ implementation to find the
// minimum number of changes required
// such that every path from top left
// to the bottom right
// are palindromic paths
  
#include <bits/stdc++.h>
using namespace std;
#define M 3
#define N 3
  
// Function to find the minimum number
// of the changes required for the
// every path to be palindromic
int minchanges(int mat[N][M])
{
    // count variable for
    // maintaining total changes.
    int count = 0;
  
    // left and right variables for
    // keeping distance values
    // from cell(0, 0) and
    // (N-1, M-1) respectively.
    int left = 0, right = N + M - 2;
  
    while (left < right) {
  
        unordered_map<int, int> mp;
        int totalsize = 0;
  
        // Iterating over the matrix
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (i + j == left) {
                    mp[(mat[i][j])]++;
                    totalsize++;
                }
                else if (i + j == right) {
                    mp[(mat[i][j])]++;
                    totalsize++;
                }
            }
        }
  
        // Finding minimum number
        // of changes required.
        unordered_map<int, int>::iterator itr = mp.begin();
        int changes = 0;
        for (; itr != mp.end(); itr++)
            changes = max(changes, itr->second);
  
        // Minimum no. of changes will
        // be the minimum no.
        // of different values and
        // we will assume to
        // make them equals to value
        // with maximum frequency element
        count += totalsize - changes;
  
        // Moving ahead with
        // greater distance
        left++;
        right--;
    }
    return count;
}
  
// Drive Code
int main()
{
    int mat[][M]
        = { { 1, 4, 1 }, { 2, 5, 3 }, { 1, 3, 1 } };
  
    // Function Call
    cout << minchanges(mat);
    return 0;
}




// Java implementation to find the
// minimum number of changes required
// such that every path from top left
// to the bottom right are palindromic
// paths
import java.io.*;
import java.util.*;
  
class GFG {
  
    static final int M = 3;
    static final int N = 3;
  
    // Function to find the minimum number
    // of the changes required for the
    // every path to be palindromic
    static int minchanges(int[][] mat)
    {
  
        // count variable for
        // maintaining total changes.
        int count = 0;
  
        // left and right variables for
        // keeping distance values
        // from cell(0, 0) and
        // (N-1, M-1) respectively.
        int left = 0, right = N + M - 2;
  
        while (left < right) {
            Map<Integer, Integer> mp = new HashMap<>();
  
            int totalsize = 0;
  
            // Iterating over the matrix
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (i + j == left) {
                        mp.put(mat[i][j],
                               mp.getOrDefault(mat[i][j], 0)
                                   + 1);
                        totalsize++;
                    }
                    else if (i + j == right) {
                        mp.put(mat[i][j],
                               mp.getOrDefault(mat[i][j], 0)
                                   + 1);
                        totalsize++;
                    }
                }
            }
  
            // Finding minimum number
            // of changes required.
            int changes = 0;
            for (Map.Entry<Integer, Integer> itr :
                 mp.entrySet())
                changes = Math.max(changes, itr.getValue());
  
            // Minimum no. of changes will
            // be the minimum no.
            // of different values and
            // we will assume to
            // make them equals to value
            // with maximum frequency element
            count += totalsize - changes;
  
            // Moving ahead with
            // greater distance
            left++;
            right--;
        }
        return count;
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        int mat[][]
            = { { 1, 4, 1 }, { 2, 5, 3 }, { 1, 3, 1 } };
     
        // Function Call
        System.out.println(minchanges(mat));
    }
}
  
// This code is contributed by offbeat




# Python3 implementation to find the
# minimum number of changes required
# such that every path from top left
# to the bottom right
# are palindromic paths
M = 3
N = 3
  
# Function to find the minimum number
# of the changes required for the
# every path to be palindromic
  
  
def minchanges(mat):
      
    # count variable for
    # maintaining total changes.
    count = 0
  
    # left and right variables for
    # keeping distance values
    # from cell(0, 0) and
    # (N-1, M-1) respectively.
    left = 0
    right = N + M - 2
  
    while (left < right):
        mp = {}
        totalsize = 0
  
        # Iterating over the matrix
        for i in range(N):
            for j in range(M):
                if (i + j == left):
                    mp[(mat[i][j])] =
                    mp.get(mat[i][j], 0) + 1
                    totalsize += 1
                elif (i + j == right):
                    mp[(mat[i][j])] =
                    mp.get(mat[i][j], 0) + 1
                    totalsize += 1
  
        # Finding minimum number
        # of changes required.
        changes = 0
        for itr in mp:
            changes = max(changes, mp[itr])
  
        # Minimum no. of changes will
        # be the minimum no.
        # of different values and
        # we will assume to
        # make them equals to value
        # with maximum frequency element
        count += totalsize - changes
  
        # Moving ahead with
        # greater distance
        left += 1
        right -= 1
    return count
  
  
# Driver Code
if __name__ == '__main__':
    mat = [[1, 4, 1],
           [2, 5, 3],
           [1, 3, 1]]
      
    # Function Call
    print(minchanges(mat))
  
# This code is contributed by Mohit Kumar 29




// C# implementation to find the
// minimum number of changes required
// such that every path from top left
// to the bottom right are palindromic
// paths
using System;
using System.Collections;
using System.Collections.Generic;
  
class GFG {
  
    static int M = 3;
    static int N = 3;
  
    // Function to find the minimum number
    // of the changes required for the
    // every path to be palindromic
    static int minchanges(int[, ] mat)
    {
  
        // count variable for
        // maintaining total changes.
        int count = 0;
  
        // left and right variables for
        // keeping distance values
        // from cell(0, 0) and
        // (N-1, M-1) respectively.
        int left = 0, right = N + M - 2;
  
        while (left < right) {
            Dictionary<int, int> mp
                = new Dictionary<int, int>();
            int totalsize = 0;
  
            // Iterating over the matrix
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (i + j == left) {
                        if (mp.ContainsKey(mat[i, j])) {
                            mp[(mat[i, j])]++;
                        }
                        else {
                            mp[(mat[i, j])] = 1;
                        }
                        totalsize++;
                    }
                    else if (i + j == right) {
                        if (mp.ContainsKey(mat[i, j])) {
                            mp[(mat[i, j])]++;
                        }
                        else {
                            mp[(mat[i, j])] = 1;
                        }
                        totalsize++;
                    }
                }
            }
  
            // Finding minimum number
            // of changes required.
            int changes = 0;
            foreach(KeyValuePair<int, int> itr in mp)
            {
                changes = Math.Max(changes, itr.Value);
            }
  
            // Minimum no. of changes will
            // be the minimum no.
            // of different values and
            // we will assume to
            // make them equals to value
            // with maximum frequency element
            count += totalsize - changes;
  
            // Moving ahead with
            // greater distance
            left++;
            right--;
        }
        return count;
    }
  
    // Driver Code
    public static void Main(string[] args)
    {
        int[, ] mat
            = { { 1, 4, 1 }, { 2, 5, 3 }, { 1, 3, 1 } };
  
        // Function Call
        Console.Write(minchanges(mat));
    }
}
  
// This code is contributed by rutvik_56




<script>
  
// Javascript implementation to find the
// minimum number of changes required
// such that every path from top left
// to the bottom right
// are palindromic paths
var M = 3
var N = 3;
  
// Function to find the minimum number
// of the changes required for the
// every path to be palindromic
function minchanges(mat)
{
    // count variable for
    // maintaining total changes.
    var count = 0;
  
    // left and right variables for
    // keeping distance values
    // from cell(0, 0) and
    // (N-1, M-1) respectively.
    var left = 0, right = N + M - 2;
  
    while (left < right) {
  
        var mp = new Map();
        var totalsize = 0;
  
        // Iterating over the matrix
        for (var i = 0; i < N; i++) {
            for (var j = 0; j < M; j++) {
                if (i + j == left || i + j == right) {
                    if(mp.has(mat[i][j]))
                        mp.set(mat[i][j], mp.get(mat[i][j])+1)
                    else
                        mp.set(mat[i][j], 1)
                    totalsize++;
                }
            }
        }
  
        var changes = 0;
        // Finding minimum number
        // of changes required.
        mp.forEach((value, key) => {
            changes = Math.max(changes, value);
        });
          
  
        // Minimum no. of changes will
        // be the minimum no.
        // of different values and
        // we will assume to
        // make them equals to value
        // with maximum frequency element
        count += totalsize - changes;
  
        // Moving ahead with
        // greater distance
        left++;
        right--;
    }
    return count;
}
  
// Drive Code
var mat
    = [ [ 1, 4, 1 ], [ 2, 5, 3 ], [ 1, 3, 1 ] ];
// Function Call
document.write( minchanges(mat));
  
// This code is contributed by importantly.
</script>

Output: 
2

Performance Analysis: 

Efficient Approach:

Algorithm:

Below is the implementation of the above approach:




// C++ Program to count minimum change
// required to convert all the paths
// pallindromic from top left to
// right bottom cell.
#include <bits/stdc++.h>
using namespace std;
  
// Function to find the minimum number
// of the changes required for the
// every path to be palindromic
int minchanges(vector<vector<int> >& a)
{
    int res = 0; // use to store final result
  
    // Row and column
    int N = a.size(), M = a[0].size();
  
    // mp_key -> (i+j) , mp_value -> nw_map
    // nw_map_key -> elements_of_matrix
    // nw_map_value -> frequency of elements
  
    // 2-D map
    map<int, map<int, int> > mp;
  
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
              
            // calculating position
            int ind = i + j;
              
            // increase the frequency of a[i][j]
            // at position ind
            mp[ind][a[i][j]]++;
        }
    }
      
    // Define left and right limit
    int r = M + N - 2, l = 0;
    while (l < r) {
          
        // s-> count total number of elements
        // at index l and r
        // mx-> store maximum frequency of any element
        int s = 0, mx = 0;
  
        // store all elements frequency at index l
        for (auto x : mp[r]) {
            mp[l][x.first] += x.second;
        }
  
        // Count total elements and mx->max_frequency
        for (auto x : mp[l]) {
            s += x.second;
            mx = max(x.second, mx);
        }
  
        // We will replace (s-mx) elements with
        // the element whose frequency is mx
        res += (s - mx);
        l++;
        r--;
    }
    
    // return res
    return res; 
}
  
// Driver Code
int main()
{
    // Function Call
    vector<vector<int> > mat
        = { { 1, 4, 1 }, { 2, 5, 3 }, { 1, 3, 1 } };
    cout << "Total number of changes requires "
         << minchanges(mat) << "\n";
  
    // Function Call
    vector<vector<int> > mat1
        = { { 1, 4 }, { 2, 5 }, { 1, 3 }, { 2, 5 } };
    cout << "Total number of changes requires "
         << minchanges(mat1) << "\n";
    
    return 0;
}
  
// This code is contributed by ajaykr00kj




import java.util.*;
  
class Main {
    
  // Function to find the minimum number
  // of the changes required for the
  // every path to be palindromic
  public static int minchanges(int[][] a) {
    int res = 0; // use to store final result
  
    // Row and column
    int N = a.length;
    int M = a[0].length;
  
    // mp_key -> (i+j) , mp_value -> nw_map
    // nw_map_key -> elements_of_matrix
    // nw_map_value -> frequency of elements
  
    // 2-D dictionary
    Map<Integer, Map<Integer, Integer>> mp = new HashMap<>();
  
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < M; j++) {
  
        // calculating position
        int ind = i + j;
  
        // increase the frequency of a[i][j]
        // at position ind
        if (!mp.containsKey(ind)) {
          mp.put(ind, new HashMap<>());
        }
        mp.get(ind).put(a[i][j], mp.get(ind).getOrDefault(a[i][j], 0) + 1);
      }
    }
  
    // Define left and right limit
    int r = M + N - 2;
    int l = 0;
    while (l < r) {
  
      // s-> count total number of elements
      // at index l and r
      // mx-> store maximum frequency of any element
      int s = 0;
      int mx = 0;
  
      // store all elements frequency at index l
      for (int x : mp.get(r).keySet()) {
        if (!mp.containsKey(l)) {
          mp.put(l, new HashMap<>());
        }
        mp.get(l).put(x, mp.get(l).getOrDefault(x, 0) + mp.get(r).get(x));
      }
  
      // Count total elements and mx->max_frequency
      for (int x : mp.get(l).keySet()) {
        s += mp.get(l).get(x);
        mx = Math.max(mp.get(l).get(x), mx);
      }
  
      // We will replace (s-mx) elements with
      // the element whose frequency is mx
      res += (s - mx);
      l++;
      r--;
    }
  
    // return res
    return res;
  }
  
  // Driver Code
  public static void main(String[] args) {
    // Function Call
    int[][] mat = {{1, 4, 1}, {2, 5, 3}, {1, 3, 1}};
    System.out.println("Total number of changes required: " + minchanges(mat));
  
    // Function Call
    int[][] mat1 = {{1, 4}, {2, 5}, {1, 3}, {2, 5}};
    System.out.println("Total number of changes required: " + minchanges(mat1));
  }
}




# Python program to count minimum change
# required to convert all the paths
# pallindromic from top left to
# right bottom cell.
  
# Function to find the minimum number
# of the changes required for the
# every path to be palindromic
def minchanges(a):
    res = 0  # use to store final result
  
    # Row and column
    N = len(a)
    M = len(a[0])
  
    # mp_key -> (i+j) , mp_value -> nw_map
    # nw_map_key -> elements_of_matrix
    # nw_map_value -> frequency of elements
  
    # 2-D dictionary
    mp = {}
  
    for i in range(N):
        for j in range(M):
  
            # calculating position
            ind = i + j
  
            # increase the frequency of a[i][j]
            # at position ind
            if ind not in mp:
                mp[ind] = {}
            mp[ind][a[i][j]] = mp[ind].get(a[i][j], 0) + 1
  
    # Define left and right limit
    r = M + N - 2
    l = 0
    while l < r:
  
        # s-> count total number of elements
        # at index l and r
        # mx-> store maximum frequency of any element
        s = 0
        mx = 0
  
        # store all elements frequency at index l
        for x in mp[r]:
            if l not in mp:
                mp[l] = {}
            mp[l][x] = mp[l].get(x, 0) + mp[r][x]
  
        # Count total elements and mx->max_frequency
        for x in mp[l]:
            s += mp[l][x]
            mx = max(mp[l][x], mx)
  
        # We will replace (s-mx) elements with
        # the element whose frequency is mx
        res += (s - mx)
        l += 1
        r -= 1
  
    # return res
    return res
  
# Driver Code
if __name__ == '__main__':
    # Function Call
    mat = [[1, 4, 1], [2, 5, 3], [1, 3, 1]]
    print("Total number of changes required: ",
          minchanges(mat))
  
    # Function Call
    mat1 = [[1, 4], [2, 5], [1, 3], [2, 5]]
    print("Total number of changes required: ",
          minchanges(mat1))




using System;
using System.Collections.Generic;
  
class Program
{
    // Function to find the minimum number
    // of the changes required for the
    // every path to be palindromic
    static int MinChanges(List<List<int>> a)
    {
        int res = 0; // use to store final result
  
        // Row and column
        int N = a.Count, M = a[0].Count;
  
        // mp_key -> (i+j) , mp_value -> nw_map
        // nw_map_key -> elements_of_matrix
        // nw_map_value -> frequency of elements
  
        // 2-D dictionary
        Dictionary<int, Dictionary<int, int>> mp = new Dictionary<int
                        Dictionary<int, int>>();
  
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < M; j++)
            {
                // calculating position
                int ind = i + j;
  
                // increase the frequency of a[i][j]
                // at position ind
                if (!mp.ContainsKey(ind))
                    mp[ind] = new Dictionary<int, int>();
                if (!mp[ind].ContainsKey(a[i][j]))
                    mp[ind][a[i][j]] = 0;
                mp[ind][a[i][j]]++;
            }
        }
  
        // Define left and right limit
        int r = M + N - 2, l = 0;
        while (l < r)
        {
            // s-> count total number of elements
            // at index l and r
            // mx-> store maximum frequency of any element
            int s = 0, mx = 0;
  
            // store all elements frequency at index l
            if (!mp.ContainsKey(r))
                mp[r] = new Dictionary<int, int>();
            foreach (var x in mp[r])
            {
                if (!mp.ContainsKey(l))
                    mp[l] = new Dictionary<int, int>();
                if (!mp[l].ContainsKey(x.Key))
                    mp[l][x.Key] = 0;
                mp[l][x.Key] += x.Value;
            }
  
            // Count total elements and mx->max_frequency
            foreach (var x in mp[l])
            {
                s += x.Value;
                mx = Math.Max(x.Value, mx);
            }
  
            // We will replace (s-mx) elements with
            // the element whose frequency is mx
            res += (s - mx);
            l++;
            r--;
        }
  
        // return res
        return res;
    }
  
    // Driver Code
    static void Main(string[] args)
    {
        // Function Call
        List<List<int>> mat = new List<List<int>>()
        {
            new List<int>() { 1, 4, 1 },
            new List<int>() { 2, 5, 3 },
            new List<int>() { 1, 3, 1 }
        };
        Console.WriteLine("Total number of changes required: " + MinChanges(mat));
  
        // Function Call
        List<List<int>> mat1 = new List<List<int>>()
        {
            new List<int>() { 1, 4 },
            new List<int>() { 2, 5 },
            new List<int>() { 1, 3 },
            new List<int>() { 2, 5 }
        };
        Console.WriteLine("Total number of changes required: " + MinChanges(mat1));
    }
}




// Function to find the minimum number
// of the changes required for the
// every path to be palindromic
function minchanges(a) {
    let res = 0; // use to store final result
      
    // Row and column
    let N = a.length, M = a[0].length;
      
    // mp_key -> (i+j) , mp_value -> nw_map
    // nw_map_key -> elements_of_matrix
    // nw_map_value -> frequency of elements
      
    // 2-D map
    let mp = new Map();
      
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < M; j++) {
              
            // calculating position
            let ind = i + j;
              
            // increase the frequency of a[i][j]
            // at position ind
            if(mp.has(ind)){
                let nw_map = mp.get(ind);
                if(nw_map.has(a[i][j]))
                    nw_map.set(a[i][j], nw_map.get(a[i][j])+1);
                else
                    nw_map.set(a[i][j], 1);
                mp.set(ind, nw_map);
            }else{
                let nw_map = new Map();
                nw_map.set(a[i][j], 1);
                mp.set(ind, nw_map);
            }
        }
    }
      
    // Define left and right limit
    let r = M + N - 2, l = 0;
    while (l < r) {
          
        // s-> count total number of elements
        // at index l and r
        // mx-> store maximum frequency of any element
        let s = 0, mx = 0;
      
        // store all elements frequency at index l
        if(mp.has(r)){
            let nw_map_r = mp.get(r);
            for (const [key, value] of nw_map_r.entries()) {
                if(mp.has(l)){
                    let nw_map_l = mp.get(l);
                    if(nw_map_l.has(key))
                        nw_map_l.set(key, nw_map_l.get(key)+value);
                    else
                        nw_map_l.set(key, value);
                    mp.set(l, nw_map_l);
                }else{
                    let nw_map_l = new Map();
                    nw_map_l.set(key, value);
                    mp.set(l, nw_map_l);
                }
            }
        }
      
        // Count total elements and mx->max_frequency
        if(mp.has(l)){
            let nw_map_l = mp.get(l);
            for (const [key, value] of nw_map_l.entries()) {
                s += value;
                mx = Math.max(value, mx);
            }
        }
      
        // We will replace (s-mx) elements with
        // the element whose frequency is mx
        res += (s - mx);
        l++;
        r--;
    }
      
    // return res
    return res; 
}
  
// Driver Code
// Function Call
let mat = [ [ 1, 4, 1 ], [ 2, 5, 3 ], [ 1, 3, 1 ] ];
console.log(`Total number of changes requires: ${minchanges(mat)}`);
  
// Function Call
let mat1 = [ [ 1, 4 ], [ 2, 5 ], [ 1, 3 ], [ 2, 5 ] ];
console.log(`Total number of changes requires: ${minchanges(mat1)}`);

Output
Total number of changes requires 2
Total number of changes requires 3

Time Complexity: O(m*n)

Space Complexity: O(m*n)


Article Tags :