题目描述
现有一棵n个节点构成的二叉树,请你将每一层的节点向右循环位移k位。某层向右位移一位(即k=1)的含义为:
1.若当前节点为左孩子节点,会变成当前节点的双亲节点的右孩子节点。
2.若当前节点为右儿子,会变成当前节点的双亲节点的右边相邻兄弟节点的左孩子节点。(如果当前节点的双亲节点已经是最右边的节点了,则会变成双亲节点同级的最左边的节点的左孩子节点)
3.该层的每一个节点同时进行一次位移。
4.是从最下面的层开始位移,位移完每一层之后,再向上,直到根节点,位移完毕。
解题思路:分层递归+右移取模
假设我们知道树的某一层的全部节点,构成一个数组v1(v1不能包含空节点)。那么我们很容易得到下一层的全部节点构成的数组v2。易知v2的长度是v1的二倍。
令v2数组的长度为n。我们对v2的每个节点v2[i]右移k次,其最终位置在(i + k) % n处。这样就得到一个新的v2数组。
此时再根据v1与v2的对应关系,重新设置v1中每个节点的左右孩子节点,右移完成!
接下来将v2数组中的空节点全部移除,然后就能得到其更下一层的全部节点构成的数组v3。重复上述步骤,完成每一层的节点右移。
下面给出c++代码。
/** * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * }; */ class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param root TreeNode类 * @param k int整型 * @return TreeNode类 */ TreeNode* cyclicShiftTree(TreeNode* root, int k) { vector<TreeNode*> next(1, root); fun(next, k); return root; } void fun(vector<TreeNode*> &v, int k) { if(v.size() == 0) return; int n = v.size() + v.size(); int pos = k % n; //下标0的元素右移k次后的位置 vector<TreeNode*> son(n + pos); //将数组容量增加pos for(auto & node : v) { son[pos++] = node->left; son[pos++] = node->right; } for(int i = son.size() - 1; i >= n; --i) { son[i - n] = son[i]; //将超出n范围的元素放回[0, n-1]区间内 } for(int i = 0; i < v.size(); ++i) { //重新设置v数组中每个节点的左右孩子(右移k次后) int i2 = i + i; v[i]->left = son[i2]; v[i]->right = son[i2 + 1]; } vector<TreeNode*> next; for(int i = 0; i < n; ++i) { if(son[i]) next.push_back(son[i]); //去掉其中的空节点 } fun(next, k); //递归下一层 } };