4.14
54. 螺旋矩阵 - 力扣(LeetCode)
法一:偏移量法
问题分析
- 方向数组顺序错误:
- 原代码的方向数组为
dirs = {{1,0}, {0,-1}, {-1,0}, {0,1}},对应方向顺序为 下→左→上→右。- 正确的螺旋遍历顺序应为 右→下→左→上,即方向数组应为
{{0,1}, {1,0}, {0,-1}, {-1,0}}。- 越界移动:
- 当检测到下一步越界时,会切换方向,但直接按新方向移动可能导致新的位置越界。
- 例如:初始方向错误导致移动路径偏离,后续方向切换无法纠正,最终访问非法内存。
//越界代码
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
int dirs[4][2] ={{1 , 0} , {0 , -1} , {-1 , 0} , { 0 , 1}};//错误行
//int dirs[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}}; 对应的才是右下左上
//因为走的时候是x = x + 0(对应行) y = y + 1(对应列),而不是平时的xy轴
vector<int> ans(m * n);
int i = 0 , j = 0 , dir = 0;
for (int k = 0 ; k < m * n; k++) {
ans[k] = matrix[i][j];
matrix[i][j] = INT_MAX;
int x = i + dirs[dir][0];
int y = j + dirs[dir][1];
if(x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] == INT_MAX){
dir = (dir + 1) % 4;
}
i += dirs[dir][0];
j += dirs[dir][1];
}
return ans;
}
};
法二:模拟
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int l = 0;
int r = matrix[0].size() - 1; //列数
int t = 0; //top上边界
int b = matrix.size() - 1; //bottom下边界
vector<int> res;
while(1){
//左->右
for (int i = l ; i <= r ; i ++) res.push_back(matrix[t][i]);
//紧接着往下,收缩上边界,判断此时上下是否重合
if(++ t > b) break;
//上->下
for (int i = t ; i <= b ; i ++) res.push_back(matrix[i][r]);
//紧接着往左,收缩右边界,判断此时左右是否重合
if(l > --r) break;
//右->左
for (int i = r ; i >= l ; i --) res.push_back(matrix[b][i]);
//紧接着往上,收缩下边界,判断此时上下是否重合
if(t > --b ) break;
//下->上
for (int i = b ; i >= t ; i --) res.push_back(matrix[i][l]);
//紧接着往右,收缩左边界,判断此时左右是否重合
if(++l > r ) break;
}
return res;
}
};
145. 二叉树的后序遍历 - 力扣(LeetCode)
迭代法:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(!root) return res;
st.push(root);
while(!st.empty()){
TreeNode* node = st.top();
st.pop();
res.push_back(node->val);//中右左 翻转-> 左右中
if(node->left) st.push(node->left);
if(node->right) st.push(node->right);
}
ranges::reverse(res);
return res;
}
};
递归法:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
auto dfs = [&](this auto&& dfs , TreeNode* node)->void{
if(!node) return;
dfs(node->left);
dfs(node->right);
res.push_back(node->val);
};
dfs(root);
return res;
}
};
199. 二叉树的右视图 - 力扣(LeetCode)
思路:先递归右子树,再递归左子树,当某个深度首次到达时,对应的节点就在右视图中。
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> ans;
auto dfs = [&](this auto&& dfs, TreeNode* node, int depth) -> void {
if (!node) return;
if (depth == ans.size()) { // 这个深度首次遇到
ans.push_back(node->val);
}
dfs(node->right, depth + 1); // 先递归右子树,保证首次遇到的一定是最右边的节点
dfs(node->left, depth + 1);
};
dfs(root, 0);
return ans;
}
};
235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)
利用二叉搜索树的性质决定往左还是往右,递归地查找。
如果p q分别在左右子树,则返回当前节点。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
int x = root->val;
if(p->val < x && q->val < x) return lowestCommonAncestor(root->left , p , q);
else if(p->val > x && q->val > x) return lowestCommonAncestor(root->right , p , q);
else return root;
}
};
695. 岛屿的最大面积 - 力扣(LeetCode)
可以不用visit数组,把访问过的
grid[x][y]全部置0
class Solution {
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
int res = 0;
int dirs[4][2] = {{-1 , 0} , {0 , 1} , {1 , 0} , {0 , -1}};
int m = grid.size() , n = grid[0].size();
int cnt = 0;
auto dfs = [&](this auto&& dfs , int x , int y)->void{
grid[x][y] = 0; //注意先把当前(x,y)置0
for (int i = 0; i < 4; i++) {
int nextx = x + dirs[i][0];
int nexty = y + dirs[i][1];
if(nextx < 0 || nextx >= m || nexty < 0 || nexty >= n) continue;
if(grid[nextx][nexty] == 1){
cnt ++;
grid[nextx][nexty] = 0;
dfs(nextx , nexty);
}
}
};
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if(grid[i][j] == 1){
cnt = 1;
dfs(i , j);
res = max(res , cnt);
}
}
}
return res;
}
};

浙公网安备 33010602011771号