本文就来看看这 3 道题目。
最大矩形有 2 道可能的题目,我们都来看下
84. 柱状图中最大的矩形
对于答案矩形也就是最大面积矩形,他的高一定是 heights 中的某个元素,那么可以遍历 heights 并且假设他是高度,那么只要计算出两边的长度即可,长度如何计算?还是用到单调栈,只不过要计算 2 次,第一次是左边比当前元素小的,第二次是右边比当前元素小的。最后计算面积即可。
var largestRectangleArea = function(heights) {
let stack=new Stack()
let left=[]
let right=[]
for(let i=0;i<heights.length;i++){
let ele=heights[i]
while(!stack.isEmpty()&&stack.peek()[0]>=ele){
stack.pop()
}
if(!stack.isEmpty()){
left[i]=stack.peek()[1]
}else {
left[i]=-1
}
stack.push([ele,i])
}
stack=new Stack()
for(let i=heights.length-1;i>=0;i--){
let ele=heights[i]
while(!stack.isEmpty()&&stack.peek()[0]>=ele){
stack.pop()
}
if(!stack.isEmpty()){
right[i]=stack.peek()[1]
}else {
right[i]=heights.length
}
stack.push([ele,i])
}
let res=0
for(let i=0;i<heights.length;i++){
let ele=heights[i]
let cur=ele*(right[i]-left[i]-1)
res=Math.max(res,cur)
}
return res
};
Stack 类的定义在这里。
85. 最大矩形
看下边的橙色的部分,这完全就是上一道题呀!
那么直接调用上一道题 largestRectangleArea 方法即可。
var maximalRectangle = function(matrix) {
let m=matrix.length
let n=matrix[0].length
let rowHeights=[]
let res=0
for(let i=0;i<m;i++){
rowHeights[i]=[]
for(let j=0;j<n;j++){
let hei=0
for(let k=i;k>=0;k--){
if(matrix[k][j]==1){
hei++
}else{
break
}
}
rowHeights[i].push(hei)
}
let cur=largestRectangleArea(rowHeights[i])
res=Math.max(res,cur)
}
return res
};
297. 二叉树的序列化与反序列化
本题可以参考这篇文章。
如果给你一棵二叉树的前序遍历结果,你是否能够根据这个结果还原出这棵二叉树呢?
答案是也许可以,也许不可以,具体要看你给的前序遍历结果是否包含空指针的信息。如果包含了空指针,那么就可以唯一确定一棵二叉树,否则就不行。
那么前中后序哪一种遍历顺序,只要序列化的结果中包含了空指针的信息,就能还原出唯一的一棵二叉树了?
但很不幸,正确答案是,即便你包含了空指针的信息,也只有前序和后序的遍历结果才能唯一还原二叉树,中序遍历结果做不到。因为前序/后序遍历的结果中,可以确定根节点的位置,而中序遍历的结果中,根节点的位置是无法确定的。
结论:
-
如果你的序列化结果中不包含空指针的信息,且你只给出一种遍历顺序,那么你无法还原出唯一的一棵二叉树。
-
如果你的序列化结果中不包含空指针的信息,且你会给出两种遍历顺序,那么分两种情况:
2.1. 如果你给出的是前序和中序,或者后序和中序,那么你可以还原出唯一的一棵二叉树。
2.2. 如果你给出前序和后序,那么除非你的整棵树中不包含值相同的节点,否则你无法还原出唯一的一棵二叉树。
-
如果你的序列化结果中包含空指针的信息,且你只给出一种遍历顺序,也要分两种情况:
3.1. 如果你给出的是前序或者后序,那么你可以还原出唯一的一棵二叉树。
3.2. 如果你给出的是中序,那么除非你的整棵树中不包含值相同的节点,否则你无法还原出唯一的一棵二叉树。
那么我们使用前序遍历加尾节点的方式序列化。
var serialize = function(root) {
let list=[]
function dfs(ele){
if(ele==null){
list.push('#')
return
}
list.push(ele.val)
dfs(ele.left)
dfs(ele.right)
}
dfs(root)
let res=list.join(',')
console.log(res)
return res
};
输出
1,2,#,#,3,4,#,#,5,#,#
反序列化也是类似的操作
var deserialize = function(data) {
let list=data.split(',')
function deser(list){
if(!list.length){
return null
}
let root=list.shift()
if(root==='#'){
return null
}
let node=new TreeNode(root)
node.left=deser(list)
node.right=deser(list)
return node
}
return deser(list)
};
主要是先把根元素找到,之后构造 left 和 right 节点。
10. 正则表达式匹配
这题是动态规划,比较难想,直接看题解并记住。
function isMatch(s, p) {
let m=s.length,n=p.length
let dp=[]
for(let i=0;i<m+1;i++){
dp[i]=[]
for(let j=0;j<n+1;j++){
dp[i][j]=false
}
}
dp[0][0]=true
for(let j=1;j<n+1;j++){
if(p[j-1]==='*'){
dp[0][j]=dp[0][j-2]
}
}
for(let i of range(1,m+1)){
for(let j of range(1,n+1)){
if(s[i-1]===p[j-1]||p[j-1]==='.'){
dp[i][j]=dp[i-1][j-1]
} else if (p[j-1]==='*'){
if(s[i-1]!=p[j-2]&&p[j-2]!='.'){
dp[i][j]=dp[i][j-2]
}else{
dp[i][j]=dp[i][j-2]||dp[i-1][j]
}
}
}
}
return dp[m][n]
};
function range(l,r){
let res=[]
for(let i=l;i<r;i++){
res.push(i)
}
return res
}