📌  相关文章
📜  从矩阵左上角到右下角将矩阵中的所有路径转换为回文路径的最少步骤

📅  最后修改于: 2021-05-05 00:23:11             🧑  作者: Mango

给定具有N行M列的矩阵mat [] [] 。任务是找到矩阵中所需的最小变化数,以使从左上到右下的每条路径都是回文路径。在路径中,只允许从一个单元格到另一个单元格的右移和下移。
例子:

简单方法:

该问题的主要观察结果是,距前端或后端相同距离的元素相等。因此,找到与(0,0)和(N-1,M-1)等距离的所有元素,然后以最小的更改次数使所有元素相等。维护一个count变量以获取更改的总数。下面是该方法的说明:

  • 左上角和右下角可能的距离是0到N + M – 2。
  • 保持两个指针在左上角,即距离为0,而另一个则为N + M – 2。
  • 遍历矩阵,并在所有距离上保持当前距离处矩阵元素的哈希图。
  • 用所需的最少更改次数更新矩阵元素。
  • 最后,将左侧距离增加1,并将右侧距离减少1。

下面是上述方法的实现:

C++
// 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 
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 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::iterator itr = mp.begin();
        int changes = 0;
        for (; itr != mp.end(); itr++)
            changes = max(changes, itr->second);
 
        // Minimum no. of changes will
        // be the 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
// 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 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 itr :
                 mp.entrySet())
                changes = Math.max(changes, itr.getValue());
 
            // Minimum no. of changes will
            // be the 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
# 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 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#
// 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 mp
                = new Dictionary();
            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 itr in mp)
            {
                changes = Math.Max(changes, itr.Value);
            }
 
            // Minimum no. of changes will
            // be the 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


C++
// C++ Program to count minimum change
// required to convert all the paths
// pallindromic from top left to
// right bottom cell.
#include 
using namespace std;
 
// Function to find the minimum number
// of the changes required for the
// every path to be palindromic
int minchanges(vector >& 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 > 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 > mat
        = { { 1, 4, 1 }, { 2, 5, 3 }, { 1, 3, 1 } };
    cout << "Total number of changes requires "
         << minchanges(mat) << "\n";
 
    // Function Call
    vector > 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


输出:
2


性能分析:

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

高效方法:

算法:

  • 我们将使用一个哈希图来计算每个元素与顶部和底部的距离相同的频率。
  • 为此,我们将使用2D映射,其中键将是索引,而值将是另一个将对频率进行计数的映射
  • 计数频率后,我们将l = 0迭代到r = m + n-1,而l
  • 我们将(sum-f)个元素替换为频率最大的元素,并存储result + =(sum-f)
  • 打印结果

下面是上述方法的实现:

C++

// C++ Program to count minimum change
// required to convert all the paths
// pallindromic from top left to
// right bottom cell.
#include 
using namespace std;
 
// Function to find the minimum number
// of the changes required for the
// every path to be palindromic
int minchanges(vector >& 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 > 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 > mat
        = { { 1, 4, 1 }, { 2, 5, 3 }, { 1, 3, 1 } };
    cout << "Total number of changes requires "
         << minchanges(mat) << "\n";
 
    // Function Call
    vector > 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
输出
Total number of changes requires 2
Total number of changes requires 3

时间复杂度: O(m * n)

空间复杂度: O(m * n)