解题思路
这是一个构建最大树的问题。对于每个元素,需要找到其左边和右边第一个比它大的数,取较小值作为父节点。
关键点:
- 使用单调栈找左右第一个大的元素
- 栈中保持递减顺序
- 每个元素的父节点是左右第一个大的数中较小的那个
- 时间复杂度要求
算法步骤:
- 使用单调栈找左边第一个大的数
- 使用单调栈找右边第一个大的数
- 比较左右两个数,取较小值作为父节点
代码
class MaxTree {
public:
vector<int> buildMaxTree(vector<int>& A, int n) {
vector<int> result(n);
vector<int> leftBig(n);
vector<int> rightBig(n);
stack<int> st;
// 找左边第一个大的数
for (int i = 0; i < n; i++) {
while (!st.empty() && A[st.top()] < A[i]) {
st.pop();
}
leftBig[i] = st.empty() ? -1 : st.top();
st.push(i);
}
// 清空栈
while (!st.empty()) st.pop();
// 找右边第一个大的数
for (int i = n - 1; i >= 0; i--) {
while (!st.empty() && A[st.top()] < A[i]) {
st.pop();
}
rightBig[i] = st.empty() ? -1 : st.top();
st.push(i);
}
// 确定每个节点的父节点
for (int i = 0; i < n; i++) {
if (leftBig[i] == -1 && rightBig[i] == -1) {
result[i] = -1; // 根节点
} else if (leftBig[i] == -1) {
result[i] = rightBig[i];
} else if (rightBig[i] == -1) {
result[i] = leftBig[i];
} else {
result[i] = A[leftBig[i]] < A[rightBig[i]] ? leftBig[i] : rightBig[i];
}
}
return result;
}
};
import java.util.*;
public class MaxTree {
public int[] buildMaxTree(int[] A, int n) {
int[] result = new int[n];
int[] leftBig = new int[n];
int[] rightBig = new int[n];
Stack<Integer> stack = new Stack<>();
// 找左边第一个大的数
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && A[stack.peek()] < A[i]) {
stack.pop();
}
leftBig[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
// 清空栈
stack.clear();
// 找右边第一个大的数
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && A[stack.peek()] < A[i]) {
stack.pop();
}
rightBig[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
// 确定每个节点的父节点
for (int i = 0; i < n; i++) {
if (leftBig[i] == -1 && rightBig[i] == -1) {
result[i] = -1; // 根节点
} else if (leftBig[i] == -1) {
result[i] = rightBig[i];
} else if (rightBig[i] == -1) {
result[i] = leftBig[i];
} else {
result[i] = A[leftBig[i]] < A[rightBig[i]] ? leftBig[i] : rightBig[i];
}
}
return result;
}
}
class MaxTree:
def buildMaxTree(self, A, n):
result = [0] * n
left_big = [-1] * n
right_big = [-1] * n
stack = []
# Find first bigger element on the left
for i in range(n):
while stack and A[stack[-1]] < A[i]:
stack.pop()
left_big[i] = stack[-1] if stack else -1
stack.append(i)
# Clear stack
stack = []
# Find first bigger element on the right
for i in range(n-1, -1, -1):
while stack and A[stack[-1]] < A[i]:
stack.pop()
right_big[i] = stack[-1] if stack else -1
stack.append(i)
# Determine parent for each node
for i in range(n):
if left_big[i] == -1 and right_big[i] == -1:
result[i] = -1 # Root node
elif left_big[i] == -1:
result[i] = right_big[i]
elif right_big[i] == -1:
result[i] = left_big[i]
else:
result[i] = left_big[i] if A[left_big[i]] < A[right_big[i]] else right_big[i]
return result
算法及复杂度
- 算法:单调栈
- 时间复杂度:,每个元素最多入栈出栈一次
- 空间复杂度:,需要额外数组存储结果