题意:
一个以1为根结点的n个结点的二叉树,对这颗二叉树进行m次旋转。
每次旋转会指定一个结点,并让以这个结点为根的子树中的所有结点的左右儿子互换。
m次操作之后,以中序遍历的方式输出操作完之后的二叉树。
方法一:
递归
思路:直接模拟。
对于每次操作, 都递归的以这个结点为根的子树中的所有结点的左右儿子互换。最后,递归的中序遍历返回答案。
class Solution { public: vector<int> res;//中序遍历序列 vector<int> solve(int n, int m, vector<int>& l, vector<int>& r, vector<int>& k) { for(int i=0;i<m;i++){ dfs(k[i],l,r);//每次旋转操作 } inOrder(1,l,r);//中序遍历 return res; } void dfs(int x,vector<int>& l, vector<int>& r){ if(x==0)//如果遇到空节点,返回 return; dfs(l[x-1],l,r);//递归左儿子 dfs(r[x-1],l,r);//递归右儿子 swap(l[x-1],r[x-1]);//交换左右儿子节点 } void inOrder(int x,vector<int>& l, vector<int>& r){ if(x==0) return; inOrder(l[x-1],l,r);//递归左儿子 res.push_back(x); inOrder(r[x-1],l,r);//递归左儿子 } };
时间复杂度:空间复杂度:
方法二:
递归优化
思路:关键点:同一个节点被操作两遍,等效于无操作。
用数组存储每个节点被操作的次数。
如果操作数是奇数,则交换左右儿子节点,并将左右儿子节点的操作数加一,就这样一层一层深入。
class Solution { public: vector<int> res;//中序遍历序列 vector<int> solve(int n, int m, vector<int>& l, vector<int>& r, vector<int>& k) { vector<int> cnt(n+1);//存储每个节点被操作的次数 for(int i=0;i<m;i++){ cnt[k[i]]++; } dfs(1,l,r,cnt);//一次递归 inOrder(1,l,r);//中序遍历 return res; } void dfs(int x,vector<int>& l, vector<int>& r,vector<int> cnt){ if(x==0)//如果遇到空节点,返回 return; if(cnt[x]%2==1){//如果操作数是奇数,则交换左右儿子节点,并将左右儿子节点的操作数加一 cnt[l[x-1]]++; cnt[r[x-1]]++; swap(l[x-1],r[x-1]); } dfs(l[x-1],l,r,cnt);//递归左儿子 dfs(r[x-1],l,r,cnt);//递归右儿子 } void inOrder(int x,vector<int>& l, vector<int>& r){ if(x==0)//如果遇到空节点,返回 return; inOrder(l[x-1],l,r);//递归左儿子 res.push_back(x); inOrder(r[x-1],l,r);//递归左儿子 } };
时间复杂度:空间复杂度: