84. 柱状图中最大的矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:
输入: heights = [2,4]
输出: 4
提示:
1 <= heights.length <=105
0 <= heights[i] <= 104
这道题目我最开始是使用动态规划做的,时间复杂度是 O ( n 2 ) O(n^2) O(n2),空间复杂度是 O ( n 2 ) O(n^2) O(n2)。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
int maxArea = 0;
for (int i = 0; i < n; i++) {
dp[i][i] = heights[i];
if (maxArea < dp[i][i])maxArea = dp[i][i];
for (int j = i + 1; j < n; j++) {
dp[i][j] = min(dp[i][j - 1], heights[j]);
if (maxArea < (j - i + 1) * dp[i][j])maxArea = (j - i + 1) * dp[i][j];
}
}
return maxArea;
}
};
但是提交后,超时了。
后面看了题解,发现我上面的操作其实可以使用单调栈进行优化,将时间和空间复杂度都降低到 O ( n ) O(n) O(n) 复杂度。
主要思想就是维护一个单调递增栈,在这个栈中,heights 值是严格单调递增的。(即:栈中任意两个元素之间的元素都是严格大于第一个元素,小于第二个元素的)所以我们只要找到一个小于它的值,那么它右边的这些值都是大于这个值的。
这样对于一个不严格单调递增的值,我们就可以很容易找到左边比它小的第一个值。
然后倒着遍历,很快又可以找到右边比他小的第一个值。
最后遍历一遍heights,对于每一个位置,求解它的面积,并保存最大值。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int>stk;
int n = heights.size();
vector<int> left(n, 0), right(n, 0);
for (int i = 0; i < n; i++) {
while (!stk.empty() && heights[stk.top()] >= heights[i]) {
stk.pop();
}
left[i] = stk.empty() ? -1 : stk.top();
stk.push(i);
}
stk = stack<int>();
for (int i = n-1; i >= 0; i--) {
while (!stk.empty() && heights[stk.top()] >= heights[i]) {
stk.pop();
}
right[i] = stk.empty() ? n : stk.top();
stk.push(i);
}
int maxArea = 0;
for (int i = 0; i < n; i++) {
maxArea = max(maxArea, (right[i] - left[i] - 1) * heights[i]);
}
return maxArea;
}
};
94. 二叉树的中序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
#include<vector>
#include<iostream>
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 {
void digui(TreeNode* root, vector<int>& vec) {
if (root->left != nullptr)digui(root->left, vec);
vec.push_back(root->val);
if (root->right != nullptr)digui(root->right, vec);
}
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
if (root == nullptr)return result;
digui(root, result);
return result;
}
};
递归法很简单,迭代法则主要运用了栈的思想,实现如下:
// 迭代法
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> stk;
vector<int> res;
while (root != nullptr || !stk.empty()) {
while (root) {
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
res.push_back(root->val);
root = root->right;
}
return res;
}
};
85. 最大矩形
给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例 1:
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
示例 2:
输入:matrix = []
输出:0
示例 3:
输入:matrix = [[“0”]]
输出:0
示例 4:
输入:matrix = [[“1”]]
输出:1
示例 5:
输入:matrix = [[“0”,“0”]]
输出:0
提示:
r
o
w
s
=
=
m
a
t
r
i
x
.
l
e
n
g
t
h
rows == matrix.length
rows==matrix.length
c
o
l
s
=
=
m
a
t
r
i
x
[
0
]
.
l
e
n
g
t
h
cols == matrix[0].length
cols==matrix[0].length
1
<
=
r
o
w
,
c
o
l
s
<
=
200
1 <= row, cols <= 200
1<=row,cols<=200
m a t r i x [ i ] [ j ] 为 ′ 0 ′ 或 ′ 1 ′ matrix[i][j] 为 '0' 或 '1' matrix[i][j]为′0′或′1′
这道题目主要利用了上面一道题目的思路,将其转化为了 84 题。
引用一下题解的图1
#include<vector>
#include<stack>
#include<iostream>
using namespace std;
class Solution {
int largestRectangleArea(vector<int>& heights) {
stack<int>stk;
int n = heights.size();
vector<int> left(n, 0), right(n, 0);
for (int i = 0; i < n; i++) {
while (!stk.empty() && heights[stk.top()] >= heights[i]) {
stk.pop();
}
left[i] = stk.empty() ? -1 : stk.top();
stk.push(i);
}
stk = stack<int>();
for (int i = n - 1; i >= 0; i--) {
while (!stk.empty() && heights[stk.top()] >= heights[i]) {
stk.pop();
}
right[i] = stk.empty() ? n : stk.top();
stk.push(i);
}
int maxArea = 0;
for (int i = 0; i < n; i++) {
maxArea = max(maxArea, (right[i] - left[i] - 1) * heights[i]);
}
return maxArea;
}
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<int> heights(n, 0);
int maxArea = 0;
for (int j = 0; j < n; j++) {
if (matrix[0][j] == '1') {
heights[j] = 1;
maxArea = 1;
}
}
maxArea = max(maxArea, largestRectangleArea(heights));
for (int i = 1; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
heights[j]++;
}
else {
heights[j] = 0;
}
}
maxArea = max(maxArea, largestRectangleArea(heights));
}
return maxArea;
}
};
int main() {
Solution sol;
//vector<vector<char>> vec = {
// {'1','0','1','0','0'},
// {'1','0','1','1','1'},
// {'1','1','1','1','1'},
// {'1','0','0','1','0'}
//};
vector<vector<char>> vec = {
{'1'}};
cout << sol.maximalRectangle(vec);
}
96. 不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
示例 2:
输入:n = 1
输出:1
提示:
1
<
=
n
<
=
19
1 <= n <= 19
1<=n<=19
这道题目的思路就是,因为二叉树是有序的,因此,推导一下他的最优子结构如下:
把他想象成一个有序的数组,数组一共有n种情况(即各个节点分别作为root节点)
考虑这些情况,假设一共有5个节点,第2个节点作为root节点后,左边有1个,右边有3个,总共的结果就是 v e c [ 1 ] × v e c [ 3 ] vec[1]\times vec[3] vec[1]×vec[3]。
显然,1个节点有1种情况,2个节点有2种情况,然后我们从3开始遍历,进行动态规划到n即可。
二者相乘就是当前根节点下总共可能的搜索结果。
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
int numTrees(int n) {
if (n == 1) {
return 1;
}
if (n == 2) {
return 2;
}
vector<int> vec(n + 1, 0);
int res = 0;
vec[0] = 1;
vec[1] = 1;
vec[2] = 2;
for (int i = 3; i <= n; i++) {
for (int j = 1; j <= i; j++) {
int left = j - 1;
int right = i - j;
res += vec[left] * vec[right];
}
vec[i] = res;
res = 0;
}
return vec[n];
}
};
int main() {
Solution sol;
cout << sol.numTrees(4);
}
答案的题解更加简洁一些,在此也记录一下:
class Solution {
public:
int numTrees(int n) {
vector<int> G(n + 1, 0);
G[0] = 1;
G[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
G[i] += G[j - 1] * G[i - j];
}
}
return G[n];
}
};
https://leetcode.cn/problems/maximal-rectangle/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-1-8/ ↩︎