【leetcode】329二维矩阵上的最长路径(DP+DFS)

本文提供了一种解决LeetCode 329题“二维矩阵上的最长路径”的算法实现,采用动态规划(DP)结合深度优先搜索(DFS)的方法,详细介绍了代码逻辑与实现过程。

【转载】【原文地址】
leetcode329+二维矩阵上的最长路径,DP加上DFS
https://blog.youkuaiyun.com/u013554860/article/details/81320312
题目:
https://leetcode.com/problems/longest-increasing-path-in-a-matrix/description/


class Solution {
public:
    int dfs(vector<vector<int>>& matrix, vector<vector<int>>& record, int x, int y, int lastVal){
        if(x<0||x>=matrix.size()||y<0||y>=matrix[0].size()) return 0;
        if(matrix[x][y] > lastVal){
            if(record[x][y]!=0) return record[x][y];
            int left = dfs(matrix, record, x, y-1, matrix[x][y])+1;
            int right = dfs(matrix, record, x, y+1, matrix[x][y])+1;
            int top = dfs(matrix, record, x-1, y, matrix[x][y])+1;
            int bottom = dfs(matrix, record, x+1, y, matrix[x][y])+1;
            record[x][y] = max(left, max(right, max(top, bottom)));
            return record[x][y];
        }
        return 0;
    }
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        if(matrix.size()==0) return 0;
        vector<int> temp(matrix[0].size(), 0);
        vector<vector<int>> record(matrix.size(), temp);
        int longest = 0;
        for(int i=0; i<matrix.size(); i++){
            for(int j=0; j<matrix[0].size(); j++){
                longest = max(longest, dfs(matrix, record, i, j, -1));
            }
        }
        return longest;
    }
};
————————————————
版权声明:本文为优快云博主「小堃哥」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013554860/article/details/81320312
<think>首先,用户查询是关于二维数组矩阵的编程题目,特别是来自LeetCode和牛客网的。我需要基于系统级指令来构建我的回答。 系统级指令包括: - 所有行内数学表达式用 `$...$` 格式。 - 独立公式用 `$$...$$` 格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如 `[^1]`。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 用户引用了几个来源: - 引用[1]:关于一个序列计算的代码。 - 引用[2]:包含多个算法问题,如迷宫搜索、选择排序等。 - 引用[3]:一个Java代码,用于在6x6矩阵中找到大礼物价值。 - 引用[4]:剑指Offer的二维数组查找问题。 - 引用[5]:牛客网的LeetCode在线编程链接。 用户说:“我想查找与二维数组矩阵相关的编程题目,特别是来自LeetCode和牛客网的题目”,所以我的核心是提供相关编程题。 我的回答结构应该清晰: 1. **介绍**:简要解释二维数组矩阵在编程中的重要性。 2. **提供题目**:列出几个来自LeetCode和牛客网的经典二维数组矩阵题目,包括题目描述和可能的解题思路。 3. **引用来源**:自然地添加引用标识。 4. **生成相关问题**:在后,添加“相关问题”部分。 从引用中提取相关部分: - 引用[3]:直接是二维数组矩阵题目,关于大礼物价值。 - 引用[4]:二维数组中的查找问题。 - 引用[2]:提到迷宫搜索,涉及二维数组。 - 引用[5]:牛客网的LeetCode链接,但具体内容未给出。 我将基于常见知识添加更多题目,因为用户指定LeetCode和牛客网。 常见LeetCode二维数组题目: - LeetCode 74: Search a 2D Matrix(搜索二维矩阵) - LeetCode 240: Search a 2D Matrix II(搜索二维矩阵II) - LeetCode 48: Rotate Image(旋转图像) - LeetCode 54: Spiral Matrix(螺旋矩阵) - LeetCode 73: Set Matrix Zeroes(矩阵置零) 牛客网题目: - 牛客网有类似题目,如“二维数组中的查找”对应剑指Offer。 - 引用[3]的代码是牛客网的题目。 在回答中,我应该: - 描述每个题目。 - 提供解题思路或关键点。 - 使用代码块如果合适,但确保语言正确。 - 添加引用标识,如基于引用[4]讨论查找问题。 生成相关问题: - 在后,添加“相关问题”部分,列出3-5个相关的问题。 确保中文回答。 大纲回答: 1. **引言**:解释二维数组矩阵在算法题中的常见性。 2. **LeetCode题目**: - 题目1: 搜索二维矩阵LeetCode 74) - 题目2: 旋转图像(LeetCode 48) - 题目3: 螺旋矩阵(LeetCode 54) 3. **牛客网题目**: - 题目1: 二维数组中的查找(对应剑指Offer) - 题目2: 大礼物价值(基于引用[3]) 4. **其他相关题目**:如迷宫问题(基于引用[2])。 5. **解题提示**:简要说明如何解决这些题目。 6. **相关问题**:生成相关问题。 在描述时,自然地添加引用: - 对于引用[4],可以说“如引用[4]中提到的二维数组查找问题”。 - 对于引用[3],可以说“在引用[3]中给出的大礼物价值问题”。 代码块:如果提供代码,使用代码块格式。 终,生成相关问题,如: - 如何优化二维数组的搜索算法? - 二维数组动态规划的常见应用? - 等。</think>### 二维数组矩阵编程题目(LeetCode和牛客网) 二维数组(或矩阵)是编程算法题中的常见数据结构,尤其在LeetCode和牛客网的题目中频繁出现。这类题目常涉及搜索、动态规划、路径查找等算法,考察对数组遍历、边界处理和空间复杂度的掌握。以下我将基于您的查询,精选几个经典题目(均来自LeetCode或牛客网),并简要描述题目、解题思路和关键点。所有题目均真实可靠,参考了LeetCode官方题库和牛客网在线编程平台[^5]。 #### 1. **LeetCode题目:搜索二维矩阵LeetCode 74)** - **题目描述**:给定一个$m \times n$的整数矩阵,每行从左到右升序排列,且每行的第一个整数大于前一行的后一个整数。要求判断目标值`target`是否在矩阵中存在。 - **解题思路**:利用矩阵的排序特性,从右上角开始搜索(类似引用[4]中提到的二维数组查找方法)。如果`target`小于当前元素,则向左移动一列;如果大于,则向下移动一行。时间复杂度为$O(m + n)$。 - **关键点**:从右上角入手,避免暴力遍历,确保高效搜索。 - **代码示例**(Python): ```python def searchMatrix(matrix, target): if not matrix: return False m, n = len(matrix), len(matrix[0]) row, col = 0, n - 1 # 从右上角开始 while row < m and col >= 0: if matrix[row][col] == target: return True elif matrix[row][col] < target: row += 1 # 向下移动 else: col -= 1 # 向左移动 return False ``` #### 2. **LeetCode题目:旋转图像(LeetCode 48)** - **题目描述**:给定一个$n \times n$的二维矩阵,表示一个图像。要求原地旋转图像90度(顺时针)。 - **解题思路**:过分层旋转实现。对于矩阵的每一层,交换四个角的元素(例如,左上与右上、右上与右下等)。核心公式是:新位置$(i, j)$的值为原位置$(n-1-j, i)$的值。时间复杂度为$O(n^2)$,空间复杂度为$O(1)$。 - **关键点**:避免使用额外空间,过索引计算实现原地旋转。 - **数学表达**:旋转后元素位置变换为: $$ \text{new\_matrix}[i][j] = \text{matrix}[n-1-j][i] $$ - **代码示例**(Java): ```java public void rotate(int[][] matrix) { int n = matrix.length; for (int i = 0; i < (n + 1) / 2; i++) { for (int j = 0; j < n / 2; j++) { int temp = matrix[n-1-j][i]; matrix[n-1-j][i] = matrix[n-1-i][n-1-j]; matrix[n-1-i][n-1-j] = matrix[j][n-1-i]; matrix[j][n-1-i] = matrix[i][j]; matrix[i][j] = temp; } } } ``` #### 3. **牛客网题目:二维数组中的查找(对应剑指Offer)** - **题目描述**:在一个$m \times n$的二维数组中,每行从左到右升序,每列从上到下升序。判断给定`target`是否存在(引用[4]中详细描述了此问题)。 - **解题思路**:从右上角开始(类似LeetCode 74),但矩阵特性不同:每列也是升序。如果`target`小于当前元素,则左移;如果大于,则下移。时间复杂度为$O(m + n)$。 - **关键点**:利用矩阵的“行升序+列升序”特性,避免全遍历。 - **代码示例**(C语言): ```c #include <stdbool.h> bool findNumberIn2DArray(int** matrix, int matrixSize, int* matrixColSize, int target) { if (matrixSize == 0) return false; int row = 0, col = *matrixColSize - 1; // 从右上角开始 while (row < matrixSize && col >= 0) { if (matrix[row][col] == target) { return true; } else if (matrix[row][col] < target) { row++; // 向下移动 } else { col--; // 向左移动 } } return false; } ``` #### 4. **牛客网题目:大礼物价值(基于引用[3])** - **题目描述**:给定一个$6 \times 6$的矩阵`board`,每个元素表示礼物价值(值在100-1000之间)。从左上角`[0,0]`出发,每次只能向右或向下移动,到达右下角。求能获得的大价值(引用[3]提供了Java实现)。 - **解题思路**:使用动态规划(DP)。定义`dp[i][j]`为从起点到`(i,j)`的大价值。状态转移方程为: $$ dp[i][j] = \text{board}[i][j] + \max(dp[i-1][j], dp[i][j-1]) $$ 边界条件:第一行或第一列时,只能从左边或上边继承。时间复杂度为$O(mn)$。 - **关键点**:处理边界(如第一行或第一列),避免数组越界。 - **代码示例**(Java,参考引用[3]): ```java public int getMost(int[][] board) { int m = board.length, n = board[0].length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0 && j == 0) continue; else if (i == 0) board[i][j] += board[i][j-1]; // 只能从左来 else if (j == 0) board[i][j] += board[i-1][j]; // 只能从上来 else board[i][j] += Math.max(board[i-1][j], board[i][j-1]); // 取左或上大值 } } return board[m-1][n-1]; // 返回右下角值 } ``` #### 5. **其他相关题目:迷宫搜索(基于引用[2])** - **题目描述**:在二维网格中(0表示可行,1表示障碍),从起点到终点找一条路径LeetCode有类似题,如“迷宫问题”)。牛客网常考深度优先搜索(DFS)或广度优先搜索(BFS)。 - **解题思路**:DFS使用递归回溯,BFS使用队列。关键点:标记访问过的位置,防止循环。时间复杂度为$O(mn)$。 - **关键点**:处理边界和障碍,优化路径选择。 - **代码提示**(DFS递归,Python): ```python def dfs_maze(grid, start, end): directions = [(0,1), (1,0), (0,-1), (-1,0)] # 右、下、左、上 visited = set() def dfs(x, y): if (x, y) == end: return True if 0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == 0 and (x, y) not in visited: visited.add((x, y)) for dx, dy in directions: if dfs(x + dx, y + dy): return True visited.remove((x, y)) # 回溯 return False return dfs(start[0], start[1]) ``` ### 解题用建议 - **搜索类题目**(如LeetCode 74或剑指Offer):优先从矩阵角落(右上或左下)开始,利用排序特性减少时间复杂度[^4]。 - **动态规划类**(如大礼物价值):定义状态转移方程,注意边界处理(第一行或第一列)[^3]。 - **路径或迷宫问题**:DFS/BFS是基础,但需优化空间(如使用迭代代替递归)。 - 更多题目可在LeetCode或牛客网搜索“二维数组”或“矩阵”,例如: - LeetCode 54: 螺旋矩阵(输出矩阵的螺旋顺序)。 - 牛客网“矩阵路径和”(类似大礼物价值,但求小值)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值