题目描述
现有一棵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); //递归下一层
}
};



京公网安备 11010502036488号