• [Leetcode] Flatten Binary Tree to Linked List


    Flatten Binary Tree to Linked List 题解

    题目来源:https://leetcode.com/problems/


    Description

    Given a binary tree, flatten it to a linked list in-place.

    Example

    For example,
    Given

             1
            / 
           2   5
          /    
         3   4   6
    

    The flattened tree should look like:

       1
        
         2
          
           3
            
             4
              
               5
                
                 6
    

    Hints:

    If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.

    Solution

    class Solution {
    private:
        TreeNode* getTail(TreeNode *node) {
            if (node -> left == NULL && node -> right == NULL) {
                return node;
            }
            TreeNode *leftTail = node -> left;
            TreeNode *rightTail = node -> right;
            if (leftTail) {
                leftTail = getTail(leftTail);
                if (rightTail)
                    rightTail = getTail(rightTail);
                if (rightTail) {
                    leftTail -> right = node -> right;
                }
                node -> right = node -> left;
                node -> left = NULL;
                return rightTail ? rightTail : leftTail;
            }
            return getTail(rightTail);
        }
    public:
        void flatten(TreeNode* root) {
            if (root)
                getTail(root);
        }
    };
    

    解题描述

    这道题题意是,将一棵二叉树变成一个链表,树节点的right指针代表链表节点的next指针,并且要求链表元素顺序是二叉树的前序遍历。同时,要求必须原地操作,也就是只能使用指针操作构造链表,而不能申请额外空间。上面给出的做法是递归前序遍历的做法,不难理解,下面要介绍一种使用Morris遍历变种的办法,不需要使用递归也不需要使用栈来暂存节点,可以说在空间复杂度上做得很好:

    class Solution {
    public:
        void flatten(TreeNode* root) {
            TreeNode *curNode = root, *preNode = NULL;
            while (curNode) {
                if (curNode -> left) {
                    preNode = curNode -> left;
                    while (preNode -> right) // 找到左子树链表尾
                        preNode = preNode -> right;
    
                    //此时preNode为curNode左子树链表尾,将其下一节点指向右子树链表头
                    preNode -> right = curNode -> right;
    
                    //curNode是当前链表头,下一节点指向左子树链表头
                    curNode -> right = curNode -> left;
    
                    curNode -> left = NULL; // 将左子树指向空
                }
    
                // 链表指针向后移动,模拟递归前序遍历
                curNode = curNode -> right;
            }
        }
    };
    
  • 相关阅读:
    Android编译系统环境过程初始化分析【转】
    Android内核开发:理解和掌握repo工具【转】
    QQ空间如何设置被删除的好友不能访问空间
    用简单的C语言实现多任务轮流切换(模拟操作系统线程机制)【转】
    可重入函数与不可重入函数【转】
    关于链表中头指针和头结点的理解【转】
    C语言中static的使用方法【转】
    指针与地址的区别【转】
    柔性数组【转】
    void及void指针介绍【转】
  • 原文地址:https://www.cnblogs.com/yanhewu/p/8424458.html
Copyright © 2020-2023  润新知