思路:
- 给出的序列是中序遍历的叶子节点,也就是每个值都只能和其左边或者右边结合成左右子树的叶子节点。
[1,2,3,4]
,比如2只能和1或者3组成左右子树的叶子节点 - 构造的树有点类似于哈夫曼树,就是希望最小的叶子节点处于最下面,即计算次数最多,从底向上就是先进行计算的,需要找到当前叶子节点极小值。
- 所以入栈的都是比栈顶小的值,只有找到比栈顶大的值,栈顶才是找到的极小值。
- 单调递减栈
- 当找到栈顶极小值时,栈顶可以和左右两边的最小值构成左右子树节点,
stack[top-1]和arr[i]
中的最小值 - 在栈顶部加一个最大值,可以不用考虑top-1是否出界
- 如果遍历完整个数组,栈中还有值,那么就是单调递减的序列,每一个栈顶都是当前极小值,所以就可以直接进行计算。
#include<stdio.h>
#include<string.h>
#define max(a,b) ((a)>(b)?a:b)
#define min(a,b) ((a)<(b)?a:b)
//单调递减栈
int mctFromLeafValues(int* arr, int arrSize){
int i=0,top=0;
int res = 0;
int stack[arrSize+1];
stack[0] = 16;
while (i<arrSize)
{
if (top<1)
{
stack[++top]=arr[i++];
}
else {
//单调递减,当前最小,入栈
if(arr[i]<stack[top]){
stack[++top] = arr[i++];
}
else{
res = res + stack[top]*min(stack[top-1],arr[i]);
top--;
}
}
}
while (top>1)
{
res = res + stack[top]*stack[top-1];
top--;
}
return res;
}
int main(){
int arr[] = {4,3,2,1};
int re = mctFromLeafValues(arr,4);
printf("re = %d\n",re);
}