思路:
题目的主要信息:
- 一个二叉树根节点为1,l与r分别记录树的左右子节点,其中第
个对应节点为
的左右子节点
- k数组中记录将要旋转的节点,旋转的时候将其所有子树及其子节点都交换位置
- 最后输出的数组为二叉树的中序遍历
- 0表示空节点
方法一:递归
具体做法:
利用递归的思想,遍历每一个要旋转的节点,将其子节点交换位置,并递归交换子节点的子节点。需要注意的是,如果一个节点被交换了两次,那么相当于没有被交换,因此我们用一个数组统计交换次数,如果次数为奇数,我们交换一次,次数为偶数,我们不交换。
最后递归中序遍历(左根右)输出。
class Solution {
public:
void rotate(int t, vector<int> &l, vector<int> &r, vector<int>& cnt){
if(cnt[t] % 2 == 1){ //偶数不转奇数转1次
swap(l[t - 1], r[t - 1]);
cnt[l[t - 1]]++; //子树的次数也要增加
cnt[r[t - 1]]++;
}
if(l[t - 1] != 0)
rotate(l[t - 1], l, r, cnt);
if(r[t - 1] != 0)
rotate(r[t - 1], l, r, cnt);
return;
}
void inOrder(int t, vector<int> &l, vector<int> &r, vector<int>& res){ //中序输出
if(l[t - 1] != 0)
inOrder(l[t - 1], l, r, res); //递归找左子树
res.push_back(t);
if(r[t - 1] != 0)
inOrder(r[t - 1], l, r, res); //递归找右子树
return;
}
vector<int> solve(int n, int m, vector<int>& l, vector<int>& r, vector<int>& k) {
vector<int> res;
vector<int> cnt(n + 1, 0);
for(int i = 0; i < k.size(); i++)
cnt[k[i]]++; //某个节点要转的次数
rotate(1, l, r, cnt);
inOrder(1, l, r, res);
return res;
}
};复杂度分析:
- 时间复杂度:
,遍历k数组为
,中序输出为
,旋转是
- 空间复杂度:
,递归栈最大深度及辅助数组cnt
方法二:非递归
具体做法:
对于二叉树的问题,能用递归解决一般也可以用栈来辅助,使用非递归,旋转时需要先将子问题加入栈中,再交换。输出时每次需要找到最左子节点,再访问根,再访问右节点。
class Solution {
public:
vector<int> solve(int n, int m, vector<int>& l, vector<int>& r, vector<int>& k) {
vector<int> res;
vector<int> cnt(n + 1, 0);
for(int i = 0; i < k.size(); i++)
cnt[k[i]]++; //某个节点要转的次数
stack<int> s;
s.push(1);
while(!s.empty()){ //旋转
int index = s.top() - 1;
s.pop();
if(l[index] != 0){ //左子树
cnt[l[index]] += cnt[index + 1];
s.push(l[index]);
}
if(r[index] != 0){ //右子树
cnt[r[index]] += cnt[index + 1];
s.push(r[index]);
}
if(cnt[index + 1] % 2 == 1){ //偶数不交换,奇数交换一次
swap(l[index], r[index]);
}
}
vector<bool> vis(n + 1, false); //记录是否访问过
s.push(1);
int index = 0;
while(!s.empty()){ //非递归中序遍历
int root = s.top();
if(!vis[root] && l[root - 1] != 0){ //没有访问过,且左节点存在
s.push(l[root - 1]);
vis[root] = true;
continue;
}
s.pop();
res.push_back(root);
index++;
if(r[root - 1] != 0) //右子树
s.push(r[root - 1]);
}
return res;
}
};复杂度分析:
- 时间复杂度:
,遍历k数组为
,中序输出为
,旋转是
- 空间复杂度:
,栈最大空间及辅助数组cnt

京公网安备 11010502036488号