矩阵中的最长递增子序列

和上一道  最长上升子序列 思路一样,不过还是从最笨的方法开始吧,也算是记录一下思考过程。

最开始的想法是,对矩阵的每个点都来一次回溯,得到从这个点开始的最长上升子序列长度。回溯的思路就是对上下左右遍历,利用到递归,停止遍历的条件是四周的数都比它大。代码如下:

class Solution1 {
public:
    // 对矩阵的每个点直接利用回溯法 超时了
    void FindMaxLength(vector< vector<int> >& matrix, vector< vector<int> >& visited, int& maxLength, int length, int i, int j){
        if(i<0 || i>(matrix.size() - 1) || j<0 || j>(matrix[0].size() - 1)) return;
        if(i>0 && visited[i-1][j] == 0 && matrix[i-1][j] > matrix[i][j]){
            visited[i-1][j] = 1;
            length++;
            maxLength = max(length, maxLength);
            FindMaxLength(matrix, visited, maxLength, length, i-1, j);
            length--;
            visited[i-1][j] = 0;
        }
        if(i<(matrix.size() - 1) && visited[i+1][j] == 0 && matrix[i+1][j] > matrix[i][j]){
            visited[i+1][j] = 1;
            length++;
            maxLength = max(length, maxLength);
            FindMaxLength(matrix, visited, maxLength, length, i+1, j);
            length--;
            visited[i+1][j] = 0;
        }
        if(j>0 && visited[i][j-1] == 0 && matrix[i][j-1] > matrix[i][j]){
            visited[i][j-1] = 1;
            length++;
            maxLength = max(length, maxLength);
            FindMaxLength(matrix, visited, maxLength, length, i, j-1);
            length--;
            visited[i][j-1] = 0;
        }
        if(j<(matrix[0].size() - 1) && visited[i][j+1] == 0 && matrix[i][j+1] > matrix[i][j]){
            visited[i][j+1] = 1;
            length++;
            maxLength = max(length, maxLength);
            FindMaxLength(matrix, visited, maxLength, length, i, j+1);
            length--;
            visited[i][j+1] = 0;
        }
        return;
    }
    int longestIncreasingPath(vector< vector<int> >& matrix) {
        if(matrix.empty()) return 0;
        int m = matrix.size();
        int n = matrix[0].size();
        int maxLength = 1;
        int length;
        vector< vector<int> > visited(m, vector<int>(n,0));
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                length = 1;
                FindMaxLength(matrix, visited, maxLength, length, i, j);
            }
        }
        return maxLength;
    }
};

嗯...超时了。其实这里有不少冗余计算,比如说往上遍历到某个点时,如果这个点之前计算过最长上升子序列长度,那就可以直接用了,没必要再次计算,也就是可以用到动态规划的思路。代码如下:

class Solution2 {
public:
    //还是超时了
    void FindMaxLength(vector< vector<int> >& matrix, int& maxLength, int length, vector< vector<int> > Length, int i, int j){
//        if(i<0 || i>(matrix.size() - 1) || j<0 || j>(matrix[0].size() - 1)) return;
        if(i>0 && matrix[i-1][j] > matrix[i][j]){
            if(Length[i-1][j] != 0){
                maxLength = max(length+Length[i-1][j], maxLength);
            }
            else{
                length++;
                maxLength = max(length, maxLength);
                FindMaxLength(matrix, maxLength, length, Length, i-1, j);
                length--;
            }
        }
        if(i<(matrix.size() - 1) && matrix[i+1][j] > matrix[i][j]){
            if(Length[i+1][j] != 0){
                maxLength = max(length+Length[i+1][j], maxLength);
            }
            else{
                length++;
                maxLength = max(length, maxLength);
                FindMaxLength(matrix, maxLength, length, Length, i+1, j);
                length--;
            }
        }
        if(j>0 && matrix[i][j-1] > matrix[i][j]){
            if(Length[i][j-1] != 0){
                maxLength = max(length+Length[i][j-1], maxLength);
            }
            else{
                length++;
                maxLength = max(length, maxLength);
                FindMaxLength(matrix, maxLength, length, Length, i, j-1);
                length--;
            }
        }
        if(j<(matrix[0].size() - 1) && matrix[i][j+1] > matrix[i][j]){
            if(Length[i][j+1] != 0){
                maxLength = max(length+Length[i][j+1], maxLength);
            }
            else{
                length++;
                maxLength = max(length, maxLength);
                FindMaxLength(matrix, maxLength, length, Length, i, j+1);
                length--;
            }
        }
        return;
    }
    int longestIncreasingPath(vector< vector<int> >& matrix) {
        if(matrix.empty()) return 0;
        int m = matrix.size();
        int n = matrix[0].size();
        int maxLengthOfMatrix = 1;
        int maxLengthOfPoint = 1;
        vector< vector<int> > Length(m, vector<int>(n,0));
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                maxLengthOfPoint = 1;
                FindMaxLength(matrix, maxLengthOfPoint, 1, Length, i, j);
                Length[i][j] = maxLengthOfPoint;
                maxLengthOfMatrix = max(maxLengthOfMatrix, maxLengthOfPoint);
            }
        }
        return maxLengthOfMatrix;
    }
};

嗯...还是超时了。超时的原因是没有真正贯彻落实动态规划,因为上面的代码里记录最长子序列记录得不到位。实际上在对任一个点进行回溯搜索时,途径的点都是计算过最长上升子序列的,因此需要都记录下来,而在上面的代码中只对已经进行回溯的点进行记录。最终版代码如下

class Solution {
public:
    vector< vector<int> > Length;
    int FindMaxLength(vector< vector<int> >& matrix, int i, int j){
        if(Length[i][j]) return Length[i][j];
        int maxLength = 0;
        if(i>0 && matrix[i-1][j] > matrix[i][j]){
            maxLength = max(maxLength, FindMaxLength(matrix, i-1, j));
        }
        if(i<(matrix.size() - 1) && matrix[i+1][j] > matrix[i][j]){
            maxLength = max(maxLength, FindMaxLength(matrix, i+1, j));
        }
        if(j>0 && matrix[i][j-1] > matrix[i][j]){
            maxLength = max(maxLength, FindMaxLength(matrix, i, j-1));
        }
        if(j<(matrix[0].size() - 1) && matrix[i][j+1] > matrix[i][j]){
            maxLength = max(maxLength, FindMaxLength(matrix, i, j+1));
        }
        Length[i][j] = maxLength + 1;
        return Length[i][j];
    }
    int longestIncreasingPath(vector< vector<int> >& matrix) {
        if(matrix.empty()) return 0;
        int m = matrix.size();
        int n = matrix[0].size();
        int maxLengthOfMatrix = 1;
        Length.resize(m, vector<int>(n, 0));
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                Length[i][j] = FindMaxLength(matrix, i, j);
                maxLengthOfMatrix = max(maxLengthOfMatrix, Length[i][j]);
            }
        }
        return maxLengthOfMatrix;
    }
};

所以说,编程能力真的很重要啊,一份好的代码总是思路足够清晰,没有冗余计算的。

原文地址:https://www.cnblogs.com/fanmu/p/9636076.html

时间: 2024-07-31 12:52:47

矩阵中的最长递增子序列的相关文章

Leetcode之深度优先搜索(DFS)专题-DFS+记忆化 329. 矩阵中的最长递增路径(Longest Increasing Path in a Matrix)

Leetcode之深度优先搜索(DFS)专题-329. 矩阵中的最长递增路径(Longest Increasing Path in a Matrix) 深度优先搜索的解题详细介绍,点击 给定一个整数矩阵,找出最长递增路径的长度. 对于每个单元格,你可以往上,下,左,右四个方向移动. 你不能在对角线方向上移动或移动到边界外(即不允许环绕). 示例 1: 输入: nums = [ [9,9,4], [6,6,8], [2,1,1] ] 输出: 4 解释: 最长递增路径为 [1, 2, 6, 9].

[Swift]LeetCode329. 矩阵中的最长递增路径 | Longest Increasing Path in a Matrix

Given an integer matrix, find the length of the longest increasing path. From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed). E

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

题目要求: 给定一个整数矩阵,找出最长递增路径的长度. 对于每个单元格,你可以往上,下,左,右四个方向移动. 你不能在对角线方向上移动或移动到边界外(即不允许环绕). 示例: 输入: nums = [ [9,9,4], [6,6,8], [2,1,1]] 输出: 4 解释: 最长递增路径为 [1, 2, 6, 9]. class Solution { public: int dx[5] = {-1, 0, 1, 0}; int dy[5] = {0, 1, 0, -1}; int longest

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

题目: 给定一个整数矩阵,找出最长递增路径的长度. 对于每个单元格,你可以往上,下,左,右四个方向移动. 你不能在对角线方向上移动或移动到边界外(即不允许环绕). 示例 1: 输入: nums = [ [9,9,4], [6,6,8], [2,1,1]] 输出: 4 解释: 最长递增路径为 [1, 2, 6, 9].示例 2: 输入: nums = [ [3,4,5], [3,2,6], [2,2,1]] 输出: 4 解释: 最长递增路径是 [3, 4, 5, 6].注意不允许在对角线方向上移动

【python-leetcode329-深度优先搜索】矩阵中的最长递增路径

给定一个整数矩阵,找出最长递增路径的长度. 对于每个单元格,你可以往上,下,左,右四个方向移动. 你不能在对角线方向上移动或移动到边界外(即不允许环绕). 示例 1: 输入: nums = [ [9,9,4], [6,6,8], [2,1,1]] 输出: 4 解释: 最长递增路径为 [1, 2, 6, 9].示例 2: 输入: nums = [ [3,4,5], [3,2,6], [2,2,1]] 输出: 4 解释: 最长递增路径是 [3, 4, 5, 6].注意不允许在对角线方向上移动. cl

329 Longest Increasing Path in a Matrix 矩阵中的最长递增路径

Given an integer matrix, find the length of the longest increasing path.From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).Exa

求数组中最长递增子序列

编程之美有一道关于数组中最长递增子序列,题目如下: 写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度. 例如在序列1,-1,2,-3,4,-5,6,-7中,其最长的递增子序列的长度为4(如1,2,4,6),从该书给的例子我们可以知道的是其最长的递增子序列可以不连续的. 作者利用动态规划方法给了三种解法. 解法一: 根据无后效性的定义,各阶段按照一定的次序排列好之后,对于某个给定阶段的状态来说,它以前各阶段的状态无法直接影响它未来的决策,而只能间接地通过当前状态来影

编程之美5:求数组中最长递增子序列

最近楼楼被男朋友带着玩dota,有点上瘾,终于在昨天晚上作出了一个重大的决定,shift+delete删掉warIII文件夹,从此退出dota的明争暗斗.不过最近看男票已经将战场从11转到了topcoder,嗯,这是个好现象,希望楼楼也能跟着玩儿起来. 理想是美好的,唉,可是楼主还在编程之美的初级阶段啊.话不多说了,希望自己加油加油再加油!!(^o^)/~ 今天要看的一道题目是求数组中最长递增子序列. 题目简介: 写一个时间复杂度尽可能低的程序,求一个一维数组(N)个元素中的最长递增子序列的长度

最长递增子序列(LIS)求解

问题描述 最长递增子序列也称 "最长上升子序列",简称LIS ( longest increasing subsequence).设L=<a1,a2,-,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lis=<ak1,ak2,-,akm>,其中k1<k2<-<km且ak1<ak2<-<akm.求最大的m值. 如:求一个一维数组arr[i]中的最长递增子序列的长度,如在序列{ 7, 1, 6, 5, 3, 4, 8