zoukankan      html  css  js  c++  java
  • leetcode树有关题目随笔

    2019/11/22

    109题 没想到用两个指针 好在可以自己想出点东西 但是是错的错误如下:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode sortedListToBST(ListNode head) {
            int len = 1;
            ListNode cur = head; 
            while(cur.next!=null){
                len +=1;
                cur=cur.next;
            }
            return sortedListToBST(head,0,len);
        }
        private TreeNode sortedListToBST(ListNode head,int start,int end){
            int mid=(start+end)>>>1;
            ListNode cur = head;
            int i=mid;
            while(i>0){
                cur=cur.next;
                i--;
            }
            TreeNode root = new TreeNode(cur.val);
            root.left=sortedListToBST(head,start,mid-1);
            root.right=sortedListToBST(cur,mid+1,end);
            return root;
        }
    }
    View Code

    注意体会官方解法方法 3:中序遍历模拟用到的思想。

    1做过数组还原平衡二叉搜索树(推荐先做题号108),我们知道,在array中每次取中点作为根节点,左右分别构建左右子树,递归直至根节点为空。
    2链表的特性导致我们无法像数组那样通过下标访问各个元素。若想按照108题的做法,就需要设置两个指针p1 p2,p1每走一步p2走两步,这样p2结束时p1就在中点。但这样会导致每次递归都需要重复遍历链表,效率较低。
    3我们考虑是否可以让建立节点的顺序匹配链表元素顺序?这样每次建立节点时,只需要获取链表下一个元素即可。
    4使用递归模拟中序遍历过程,建立节点的顺序即与链表元素顺序一一对应,bottom-up建立树,最终返回根节点。
    5递归前需要统计链表长度n,整体算法复杂度O(N)。

    ===========================================

     后序遍历的代码

    public void PrintBinaryTreeBacRecur(TreeNode<T> root){
        if (root == null)
            return;
        
        PrintBinaryTreeBacRecur(root.right);
        PrintBinaryTreeBacRecur(root.left); 
        System.out.print(root.data);
        
    } 

    先序遍历迭代

    public static void preOrderStack(TreeNode root) {
        if (root == null) { 
            return;
        }
        Stack<TreeNode> s = new Stack<TreeNode>();
        while (root != null || !s.isEmpty()) {
            while (root != null) {
                System.out.println(root.val);
                s.push(root);
                root = root.left;
            }
            root = s.pop();
            root = root.right;
        }
    }

    还有一种特殊的先序遍历,提前将右孩子保存到栈中,我们利用这种遍历方式就可以防止右孩子的丢失了。由于栈是先进后出,所以我们先将右节点入栈。

    public static void preOrderStack(TreeNode root) {
        if (root == null){
            return;
        }
        Stack<TreeNode> s = new Stack<TreeNode>();
        s.push(root);
        while (!s.isEmpty()) {
            TreeNode temp = s.pop();
            System.out.println(temp.val);
            if (temp.right != null){
                s.push(temp.right);
            }
            if (temp.left != null){
                s.push(temp.left);
            }
        }
    }

    作者:windliang
    链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--26/
    来源:力扣(LeetCode)

    ==============================================

    113题 路径总和||

    作者:powcai
    链接:https://leetcode-cn.com/problems/path-sum-ii/solution/dfs-by-powcai-2/
    来源:力扣(LeetCode)

    class Solution {
        public List<List<Integer>> pathSum(TreeNode root, int sum) {
            List<List<Integer>> res = new ArrayList<>();
            helper(root, sum, res, new ArrayList<Integer>());
            return res;
        }
    
        private void helper(TreeNode root, int sum, List<List<Integer>> res, ArrayList<Integer> tmp) {
            if (root == null) return;
            tmp.add(root.val);
            if (root.left == null && root.right == null && sum - root.val == 0) res.add(new ArrayList<>(tmp));
            helper(root.left, sum - root.val, res, tmp);
            helper(root.right, sum - root.val, res, tmp);
            tmp.remove(tmp.size() - 1);
        }
    }

    仿照答案中更快的写法在helper中加了一个返回结果更快

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public List<List<Integer>> pathSum(TreeNode root, int sum) {
           List<List<Integer>> res = new ArrayList<>();
           helper(root,sum,res,new ArrayList<Integer>());
           return res;
        }
        public void helper(TreeNode root,int sum,List<List<Integer>> res, ArrayList<Integer> tmp){
            if(root==null) return;
            tmp.add(root.val);
            if(root.left==null&&root.right==null&&sum-root.val==0) {
                res.add(new ArrayList<>(tmp));
                tmp.remove(tmp.size()-1);
                return;
            }
            helper(root.left,sum-root.val,res,tmp);
            helper(root.right, sum - root.val, res, tmp);
            tmp.remove(tmp.size() - 1);
        }
    
    
    }

    94. 二叉树的中序遍历  2020/1/7

    二叉树的前序中序后序遍历还需要巩固巩固 一开始想到了递归的方法,但是没想出来代码

    递归方法(基本方法)迭代方法(迭代就是使用栈来做,这个思想好好学习学习)

    96. 不同的二叉搜索树 2020/1/7

    遍历每个数字 i,将该数字作为树根,1 ... (i-1) 序列将成为左子树,(i+1) ... n 序列将成为右子树 这个想法必修得有

    笛卡尔积  由于 G(n)G(n) 和序列的内容无关,只和序列的长度有关 所以从 [4, 5, 6, 7]` 构建不同右子树的数量表示为 G(4)

    或者是又叫做卡特兰数

    98. 验证二叉搜索树 2020/1/7

    一般的迭代方法肯定要会把 类似于94题 用栈迭代

    中序遍历 牛 那个方法要掌握并能想起来 按照12345在前序 中序 后序中的遍历顺序来检验

    最大值 最小值的方法真的绝了

    100. 相同的树 2020/1/8

    这里有一个大佬给的关于树的解题模板 

    void BST(TreeNode root, int target) {
        if (root.val == target)
            // 找到目标,做点什么
        if (root.val < target) 
            BST(root.right, target);
        if (root.val > target)
            BST(root.left, target);
    }

    101. 对称二叉树 2020/1/8

    注意审题!

    102. 二叉树的层次遍历 2020/1/8

    用队列来做的想法想到了 棒棒 再加一个单独的变量记录把数据放在第几个内部list中

    103. 二叉树的锯齿形层次遍历 2020/1/9

    list的add方法有两种方法,一个是add(E element)一个是add(int index,E element)

    然后就可通过一个值判断是从左往右还是从右往左 然后通过不同的add来添加数值

    或者是用addFirst和add来分别往list中添加数值

    104. 二叉树的最大深度 2020/1/9

    我靠 这个我没想到  官方解答的第一个方法 深度优先遍历 呜呜呜这么简单  

    105. 从前序与中序遍历序列构造二叉树 2020/1/30

     答主给的方法很多 采用了第二种使用HashMap的方法

    106. 从中序与后序遍历序列构造二叉树 2020/1/30

    使用到技巧 通过解方程得到下标  使用hash表能使速度更快一些  答案里有的答案更快

    107. 二叉树的层次遍历 II 2020/1/31

    BFS思想能想到 queue输入是offer!!! DFS思想 用level来控制 对于从下往上的输出 可以在list中采用add(index,new arraylist)的方法

    108. 将有序数组转换为二叉搜索树 2020/1/31

    这道题很简单的只用进行递归即可。不用想的复杂 计算一个mid值分左右

    109. 有序链表转换二叉搜索树 2020/1/31

    中序遍历模拟的方法很经典 注意node是在left_child后面进行计算的

    110. 平衡二叉树 2020/2/1

    从顶到底的思想 暴力法 结合104二叉树最大深度来考虑 

    或者是从底到顶的思想 也就是DFS 值得好好揣摩

    111. 二叉树的最小深度 2020/2/1

    当前节点左右子树有一个为空时,返回的应是非空子树的最小深度,而不是空子树深度0;若返回0相当于把当前节点认为成叶子节点,与此节点有非空子树矛盾。

    112. 路径总和 2020/2/2

    还不错 能想到

    113. 路径总和 II 2020/2/2

    回溯回溯回溯!!!

    114. 二叉树展开为链表 2020/2/2

    找到技巧 

    144. 二叉树的前序遍历 2020/1/

    145. 二叉树的//后序遍历 2020/1//

  • 相关阅读:
    CSS布局口诀
    JAVA集合框架
    java接口作用及其好处
    java 输入输出类
    Java中精确计算的一个类BigDecimal
    java 集合框架
    java JSTL标签总结
    meta标签
    Java字符串使用总结
    Java集合框架使用方法
  • 原文地址:https://www.cnblogs.com/doyi111/p/11911005.html
Copyright © 2011-2022 走看看