已知前中序遍历数组,求后序遍历数组
要求不能通过创建树来实现
看这个需要知道:通过前中序遍历怎么还原树,如果不知道,下面看懂应该很困难
思路:
先了解一下基本知识:
DLR:前序(数组分布状况:D,LLL,RRRRR)
LDR:中序(数组分布状况:LLL,D,RRRRR)
LRD:后序(数组分布状况:LLL,RRRRR,D)
遍历的时候分为三个部分:
- L:左子树(是一个部分,可能有多个元素,也可能有一个元素)
- D:当前节点(只可能是一个元素)
- R:右子树(同左子树)
综上,我们可以看出,要想得到后序遍历只需要将中序遍历的 D 挪到后面就可以了。
过程:
- 遍历前序,因为第一个元素肯定是中间节点,所以,通过这个节点将中序遍历分为三个部分(L,D,R)
- 然后将D和R的位置互换
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
vector<int>dlr;//存储前序遍历数组
vector<int>ldr;//存储中序遍历数组
vector<int>lrd(ldr);//存储后序遍历数组(需要在中序数组基础上进行修改)
//将d和r进行交换
void swapt(int l, int r) {//互换的范围
//范围内应该是这样的(D,R,R,R,R)
//执行之后应该是这样的(R,R,R,R,D)
if (l >= r) return;
int t = lrd[l];
for (int i = l; i < r; i++) {
lrd[i] = lrd[i + 1];
}
lrd[r] = t;
}
//遍历数组(dlr数组的区间[l,r],ldr数组的区间[l,r])注意事项全闭和的区间
void dfs(int dlrx, int dlry, int ldrx, int ldry) {
if (dlrx >= dlry || ldrx >= ldry) return;
//找到中间节点
int it = (int)(find(ldr.begin(), ldr.end(), dlr[dlrx]) - ldr.begin());
dfs(dlrx + 1, dlrx + it - ldrx, ldrx, it - 1);
dfs(dlrx + it - ldrx + 1, dlry, it + 1, ldry);
swapt(it, ldry);
//这里为什么使用后序的操作呢?
//因为,这样保证了每当LDR移动成LRD,就把LRD当做一个整体
//避免了因为修改导致数据错乱。
}
int main() {
dfs(0, dlr.size() - 1, 0, ldr.size() - 1);
}