找出矩阵中最长路径的长度,其中包含连续字符及其路径

Posted

技术标签:

【中文标题】找出矩阵中最长路径的长度,其中包含连续字符及其路径【英文标题】:Find the length of the longest path in the matrix with the consecutive character along with its path 【发布时间】:2020-01-18 13:51:06 【问题描述】:

给定 M * N 个字符矩阵,找出从给定源开始的矩阵中最长路径的长度。

注意:最长路径中的所有字符都应该增加并且 按字母顺序相互连续。我们是 允许在所有 8 个方向搜索下一个字符。

我已经正确地找出了序列的长度,但是路径有问题。路径不正确。 这是我的代码

#include<iostream>
#include<vector>
using namespace std;

//Below array details all 8 posible directions
int row[] =  -1,-1,-1, 0, 0, 1, 1, 1 ;
int col[] =  1, 0, -1, 1,-1, -1,0, 1 ;


int length(char arr[][5], int x, int y, char previous, vector<pair<int,int> > &path, int k)

    // x and y must be bounded between 0 to 4
    if( x < 0  || x > 4 || y > 4 || y < 0)
       return 0;

    int l = 0;
    int max_length = 0;

    for( int i = 0; i < 8; i++)
    
        // storing next character in search
        char ch = arr[x+row[i]][y+col[i]];

        //checking whether ch is the next character in the sequence or not
        if(ch == previous + 1)
          
            //if k != path.size() then we have taken back in
            // the sequence so no need to push back character in the path
            if(k == path.size())
              
                // Pushing co-ordinates of next valid character
                path.push_back(make_pair(x+row[i], y+col[i]));
              
            else
                path.pop_back();

            l = 1 + length(arr, x+row[i], y+ col[i], ch , path, ++k);
            max_length = max( l, max_length);
        

    

    return max_length;


int main()

    char arr[5][5] =  
                       'd','e','h','x','b',
                       'a','o','g','p','e',
                       'd','d','c','f','d',
                       'e','b','e','a','s',
                       'c','d','y','e','n'
                    ;
    vector<pair<int,int> > path;

    //Pusing source address
    path.push_back(make_pair(2,2));

    int k = 1;

    int Len = length(arr, 2, 2 , arr[2][2], path, k);

    cout << "Length of the Longest sequence is : " << Len + 1 <<endl; 

    //printing the path
    cout << "Path is : "<<endl;
    for( pair<int,int> i : path)
    
        cout <<"( " << i.first <<","<<i.second <<" )" ;
    

    return 0;

实际输出:

最长序列的长度为:6 路径是 ( 2,2 )( 2,1)( 3,0 )( 3,2 )( 2,3 )( 1,2 )( 0,2 )

预期输出

最长序列的长度为:6 路径是 ( 2,2 )(2,1 )( 3,2 )( 2,3 )( 1,2 )( 0,2 )

我的输出中有一个额外的 (3,0)。当我从 (3,0) 取回时,我无法弹出它。 任何帮助将不胜感激。

【问题讨论】:

(3,0) 来自哪里?您是否尝试使用调试器逐行执行代码? 【参考方案1】:

构建路径的算法不能这样工作。回溯时你有一些预知不破坏路径,但是当回溯之后——搜索再次向另一个方向加深时,路径将成为两条路径的组合:前一个分支不会从中删除。

所以在你的实际情况下,第一次尝试是从 (2,1) 到 (3,0)。在那里它发现它不能再深入了,但它是迄今为止最好的路径。然后它回溯到(2,1)。路径没有缩短(因为它仍然是最好的)。然后搜索再次加深到 (3,2)。然后将该地址添加到路径中,从而使其不一致。

它不能那样工作。当你找到一条更好的路径时,你需要创建一条新路径,并确保它永远不会再被改变。只有当你找到更好的路径时,你才完全替换它。

我还建议限制函数的参数(++k 也是一个问题——但我们可以不这样做)。让函数返回最长的路径,而不是改变路径参数。长度总是可以从中推导出来的。

所以这里是你的函数可以如何修改:

#include<iostream>
#include<vector>
using namespace std;

//Below array details all 8 posible directions
int row[] =  -1,-1,-1, 0, 0, 1, 1, 1 ;
int col[] =  1, 0, -1, 1,-1, -1,0, 1 ;

vector<pair<int,int> > longestPath(char arr[][5], int x, int y)

    char previous = arr[x][y];
    vector<pair<int,int> > path; // a new(!) path
    // x and y must be bounded between 0 to 4
    if( x < 0  || x > 4 || y > 4 || y < 0)
       return path;

    for (int i = 0; i < 8; i++)
    
        // storing next character in search
        char ch = arr[x+row[i]][y+col[i]];

        //checking whether ch is the next character in the sequence or not
        if(ch == previous + 1)
          
            vector<pair<int,int> > foundPath = longestPath(arr, x+row[i], y+ col[i]);
            if (foundPath.size() > path.size())
                path = foundPath;
        

    
    path.insert(path.begin(), make_pair(x,y));
    return path;


int main()

    char arr[5][5] =  
                       'd','e','h','x','b',
                       'a','o','g','p','e',
                       'd','d','c','f','d',
                       'e','b','e','a','s',
                       'c','d','y','e','n'
                    ;
    vector<pair<int,int> > path = longestPath(arr, 2, 2);

    //printing the path
    cout << "Path is : "<<endl;
    for( pair<int,int> i : path)
    
        cout <<"( " << i.first <<","<<i.second <<" )" ;
    

    return 0;

【讨论】:

【参考方案2】:

与其从实现开始并向我们展示 - 您应该从抽象算法(和数据结构)开始,并尽最大努力确保是合理的。另外,我建议不要过多关注单个指令和循环变量的序列,而是关注它的全局。

所以,这是一个相对幼稚的算法:

为(潜在)路径中的每个节点运行一个阶段:因此,在您的情况下,最多 26 个阶段。 在每个阶段,您都持有路径可以到达的矩阵位置集;然后你推导出这些路径可以通过另一个步骤到达的位置集。换句话说,您正在推进一条多条道路的“前沿”,一次一步。 相位动作可以通过尝试从每个前面的位置向前移动来实现(例如,检查前面的哪个 'f' 有一个相邻的 'g');或者通过尝试从具有适当相位值的每个矩阵元素向后移动(例如,搜索矩阵中的哪些 g 与前一个前面的 f 相邻。)

这与您的方法不同,因为在各个路径上没有递归。这种递归可能会很快爆发。虽然您的路径确实不能超过 26 个字符,但原则是有问题的。假设您有一个如下所示的对角矩阵:

abcde  ...
bcde  ...
cde  ...
de ...
e ...
.
.
.

左右移动的任意组合都是有效路径;所以从 a 开始有 2^k 条长度为 k 的路径。你想调用你的longestPath() 2^26 次吗?如果你不必... :-(

【讨论】:

以上是关于找出矩阵中最长路径的长度,其中包含连续字符及其路径的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 0329. 矩阵中的最长递增路径

题目地址(329. 矩阵中的最长递增路径)

leetcode之329矩阵中的最长递增路径Golang

LeetCode329. 矩阵中的最长递增路径(Java)

329. 矩阵中的最长递增路径(困难)-动态规划+DFS

329. 矩阵中的最长递增路径