在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。
示例 1:
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:4
示例 2:
输入:matrix = [[“0”,“1”],[“1”,“0”]]
输出:1
示例 3:
输入:matrix = [[“0”]]
输出:0
提示:
m = = m a t r i x . l e n g t h m == matrix.length m==matrix.length
n = = m a t r i x [ i ] . l e n g t h n == matrix[i].length n==matrix[i].length
1 < = m , n < = 300 1 <= m, n <= 300 1<=m,n<=300
matrix[i][j] 为 ‘0’ 或 ‘1’
这道题目的状态转移方程如下:
// 伪代码
if (grid[i - 1][j - 1] == '1') {
dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
}
参考自leetcode题解1。
#include
#include
using namespace std;
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
int maximal = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (matrix[i - 1][j - 1] == '1') {
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]),
dp[i - 1][j - 1]) + 1;
if (dp[i][j] > maximal) {
maximal = dp[i][j];
}
}
}
}
return maximal * maximal;
}
};
int main() {
vector<vector<char>> vec = {
{'1', '0', '1', '0', '0'},
{'1', '0', '1', '1', '1'},
{'1', '1', '1', '1', '1'},
{'1', '0', '0', '1', '0'}
};
Solution sol;
int res = sol.maximalSquare(vec);
cout << res << endl;
}
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
示例 2:
输入:root = [2,1,3]
输出:[2,3,1]
示例 3:
输入:root = []
输出:[]
提示:
树中节点数目范围在 [0, 100] 内
-100 <= Node.val <= 100
思路就是采用递归算法,翻转左子树,然后翻转右子树。
#include
using namespace std;
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) {
return nullptr;
}
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
提示:
树中节点数目在范围 [2, 105] 内。
− 1 0 9 < = N o d e . v a l < = 1 0 9 -10^9 <= Node.val <= 10^9 −109<=Node.val<=109
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。
这道题很难想到,是一道后续遍历的题目,但是需要返回遍历的状态结果给父节点,然后父节点进行判断是否是 lowestCommonAncestor
,如果是就记录下来。
官方给的题解写得就已经很清晰了:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/solution/er-cha-shu-de-zui-jin-gong-gong-zu-xian-by-leetc-2/
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
TreeNode* ans;
public:
bool dfs(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr) {
return false;
}
bool lson = dfs(root->left, p, q);
bool rson = dfs(root->right, p, q);
if ((lson && rson) || (root->val == p->val || root->val == q->val) && (lson || rson)) {
ans = root;
}
return lson || rson || (root->val == p->val || root->val == q->val);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, p, q);
return ans;
}
};
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
示例 1:
输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]
提示:
2 < = n u m s . l e n g t h < = 1 0 5 2 <= nums.length <= 10^5 2<=nums.length<=105
− 30 < = n u m s [ i ] < = 30 -30 <= nums[i] <= 30 −30<=nums[i]<=30
保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内
进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
又是一道一次就通过了的题目,主要采用前缀乘积,搞两个数组,一个作为前缀乘积,另一个作为后缀的乘积,最终的结果就是两个元素对应相乘。
复杂度为O(1)的做法其实也很简单,就是不要搞两个数组,取而代之的是搞两个变量,用这两个变量来代表当前位数左右两边的前缀和后缀乘积,但是这样后缀就要先做一遍乘法再做一遍除法,相当于用时间换空间。
#include
using namespace std;
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
vector<int> forward = vector<int>(nums.size(), 1);
vector<int> backward = vector<int>(nums.size(), 1);
for (int i = 1; i < nums.size(); i++) {
forward[i] = forward[i - 1] * nums[i - 1];
}
for (int i = nums.size() - 2; i >= 0; i--) {
backward[i] = backward[i + 1] * nums[i + 1];
}
vector<int> ans(nums.size());
for (int i = 0; i < nums.size(); i++) {
ans[i] = forward[i] * backward[i];
}
return ans;
}
};
https://leetcode.cn/problems/maximal-square/solution/li-jie-san-zhe-qu-zui-xiao-1-by-lzhlyle/ ↩︎