首页 > 试题广场 >

循环右移二叉树

[编程题]循环右移二叉树
  • 热度指数:2057 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
现有一棵个节点构成的二叉树,请你将每一层的节点向右循环位移位。某层向右位移一位(即)的含义为:
1.若当前节点为左孩子节点,会变成当前节点的双亲节点的右孩子节点。
2.若当前节点为右儿子,会变成当前节点的双亲节点的右边相邻兄弟节点的左孩子节点。(如果当前节点的双亲节点已经是最右边的节点了,则会变成双亲节点同级的最左边的节点的左孩子节点)
3.该层的每一个节点同时进行一次位移。
4.是从最下面的层开始位移,位移完每一层之后,再向上,直到根节点,位移完毕。

如果从最后一层开始对该二叉树的每一层循环位移位。以下方二叉树为例,

      1
     / \
    2   3
       / \
      4   5
位移最后一层,5变成2的左孩子节点,4变成3的右孩子节点,如下图:
      1
     / \
    2   3
   /     \
  5       4
再位移倒数第二层,3变成1的左孩子节点,2变成1的右孩子的节点,它们的孩子节点随着一起位移,如下图:
      1
     / \
    3   2
    \   /
     4 5
根节点没有双亲节点,不用位移,位移完毕

现在给你这棵二叉树,请你返回循环右移位后的二叉树。
示例1

输入

{1,2,3,#,#,4,5},1

输出

{1,3,2,#,4,5}

说明

解释见题面描述。     
示例2

输入

{1,2,3,4},2

输出

{1,2,3,#,#,4}

说明

      1
     / \
    2   3
   /
  4
变为
      1
     / \
    2   3
       /
      4
示例3

输入

{1,#,3,4,5},1

输出

{1,3,#,5,4}

说明

    1
     \
      3
     / \
    4   5
变为
    1
     \
      3
     / \
    5   4
变为
        1
       /
      3
     / \
    5   4

备注:
树的节点个数在之间,且保证该树上每个节点的编号不同,节点编号并非按顺序排列,

说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @param k int整型 
     * @return TreeNode类
     */
    public TreeNode cyclicShiftTree (TreeNode root, int k) {
        // 存储第一层节点
        Queue<TreeNode> queue1 = new LinkedList<>();
        // 存储第一层节点的子节点
        Queue<TreeNode> queue2 = new LinkedList<>();
    
        queue1.offer(root);
        addNode(queue2, root);

        while (!queue1.isEmpty()) {
            int size = queue1.size();

            moveK(queue1, k);
            moveK(queue2, k);

            while (size > 0) {
                changeNode(queue1, queue2);
                size--;
            }
        }
        return root;
    }

    public static void changeNode(Queue<TreeNode> queue1, Queue<TreeNode> queue2) {
        // 取出根节点 tmp
        TreeNode tmp = queue1.poll();

        // 为根节点添加子节点,当子节点val为0时,子节点为空
        TreeNode childLeft = queue2.poll();
        if (childLeft.val == 0) {
            tmp.left = null;
        }else {
            queue1.offer(childLeft);
            tmp.left = childLeft;
            addNode(queue2, childLeft);
        }

        TreeNode childRight = queue2.poll();
        if (childRight.val == 0) {
            tmp.right = null;
        }else {
            queue1.offer(childRight);
            tmp.right = childRight;
            addNode(queue2, childRight);
        }
}

    // 右移 k 位
    public static void moveK(Queue<TreeNode> queue, int k) {
        while (k > 0) {
            queue.offer(queue.poll());
            k--;
        }
    }

    // 添加节点
    public static void addNode(Queue<TreeNode> queue, TreeNode root) {
        if (root.val == 0) {
            return;
        }
        //  为了使得叶子节点,在右移的过程中获得子节点,将null转换为 val=0 的子节点,之后再识别出来,转化为null
        if (root.left != null) {
            queue.offer(root.left);
        }else {
            queue.offer(new TreeNode(0));
        }

        if (root.right != null) {
            queue.offer(root.right);
        }else {
            queue.offer(new TreeNode(0));
        }
  
    }

}

发表于 2023-02-18 13:19:47 回复(0)
同样的逻辑 java超时  c++A了😥
发表于 2021-12-24 21:02:22 回复(0)