• 算法——二叉树转链表转换问题


    前序遍历转换问题

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
    leetcode

    迭代

    解题思路:通过栈来中序遍历这个二叉搜索树。

    • 遍历的时候,第一次遍历到底部的时候,那个节点就是头节点。
    • 每次遍历的时候都要存下当前节点为前节点。在之后的遍历中,用前节点的right指向下一个节点节点。在用当前节点left指向前一个节点。
    • 如果这里的right和left发生对换也可以,不过迭代之后的顺序就要发生改变,因为我们每次都是去判断其右子树是否存在,如果前面就用right去指向前一个节点的话,不就进入一个循环了。
    • 最后需要把尾节点和头节点连上。
    class Solution {
        public Node treeToDoublyList(Node root) {
            Deque<Node> stack = new LinkedList<>();
            Node pre = null, head = null;
    
            if(root == null) return root;
    
            while(root != null || !stack.isEmpty()) {
                while(root != null) {
                    stack.push(root);
                    root = root.left;
                }
    
                root = stack.pop();
                if(pre == null) {
                    head = root;
                } else {
                    pre.right = root;
                    root.left = pre;
                }
    
                pre = root;
    
                root = root.right;
            }
            
            pre.right = head;
            head.left = pre;
    
            return pre;
        }
    }
    

    递归做法

    其实二者的连接思路相同。

    class Solution {
        // 1. 中序,递归
        Node pre, head;
        public Node treeToDoublyList(Node root) {
            // 边界值
            if(root == null) return null;
            dfs(root);
    
            // 题目要求头尾连接
            head.left = pre;
            pre.right = head;
            // 返回头节点
            return head;
        }
        void dfs(Node cur) {
            // 递归结束条件
            if(cur == null) return;
            dfs(cur.left);
            // 如果pre为空,就说明是第一个节点,头结点,然后用head保存头结点,用于之后的返回
            if (pre == null) head = cur;
            // 如果不为空,那就说明是中间的节点。并且pre保存的是上一个节点,
            // 让上一个节点的右指针指向当前节点
            else if (pre != null) pre.right = cur;
            // 再让当前节点的左指针指向父节点,也就连成了双向链表
            cur.left = pre;
            // 保存当前节点,用于下层递归创建
            pre = cur;
            dfs(cur.right);
        }
    }
    

    后序遍历转换问题

    给定一个二叉树,原地将它展开为一个单链表。
    leetcode

    例如,给定二叉树

        1
       / 
      2   5
     /    
    3   4   6
    将其展开为:
    
    1
     
      2
       
        3
         
          4
           
            5
             
              6
    

    递归

    利用迭代的后续遍历。

    class Solution {
        TreeNode last = null;
        public void flatten(TreeNode root) {
            if(root == null) return ;
            flatten(root.right);
            flatten(root.left);
            root.right = last;
            root.left = null;
            last = root;
    
        }
    }
    

    迭代

    利用辅助栈后序遍历二叉树,然后依次保存前一节点,然后将当前节点的左右子树指向正确位置即可。

    
    class Solution {
    
        public void flatten(TreeNode root) {
            if(root == null) return;
        
            Deque<TreeNode> stack = new LinkedList<>();
            TreeNode last = null, pre = null;
    
            while(root != null || !stack.isEmpty()) {
                while(root != null) {
                    stack.push(root);
                    root = root.right;
                }
    
                root = stack.peek();
    
                if(root.left != null && root.left != last) {
                    root = root.left;
                } else {
                    stack.pop();
                    root.left = null;
                    root.right = last;
                    last = root;
                    root = null;
                }
                
            }
        }
    }
    
  • 相关阅读:
    linux fork函数与vfork函数,exit,_exit区别
    wait、waitpid 僵尸进程 孤儿进程
    storage size of ‘oldact’ isn’t known
    xpath选择器使用
    linux read和write函数
    Sql case when用法
    linux select
    sublime使用
    notepad++使用技巧及插件汇总
    jQuery Ajax 实例 具体介绍$.ajax、$.post、$.get的使用
  • 原文地址:https://www.cnblogs.com/lippon/p/14117628.html
Copyright © 2020-2023  润新知