处理二叉树某个节点时是通过O(1)的操作将规模为n的问题分解为两个规模为n/2的问题,即T(n)=2T(n/2)+O(1)=O(n) 即使该节点两个分叉不均匀也是O(n)
如果用O(n)的操作的话时间复杂度就是O(nlogn) 每层的操作时间均是O(n) 画树形图分析
二叉树遍历:前序遍历——根左右 中序遍历——左根右 后序遍历——左右根
二叉查找树:左边小,右边大 BST的中序遍历是不下降序列
递归三要素:
1、递归的定义:递归做了什么事情 这样能确定返回值、传入参数、调用
2、递归的拆解:把大象装进冰箱总共需要几步,第一部干嘛第二部干嘛…
3、递归的出口:退出条件 一般是root==null或者root只有一个节点
二叉树中的递归:分治法和遍历:
遍历和分治法有细微的差别,最明显的区别是返回值不同,traverse的返回值是void,所有结果都存储在同一个数组中,共享一个result,因此需要传入一个全局变量,相当于一个人走。而divide and conquer的返回值是一个数组,是每一层都存储在一个数组中,最终合并起来,相当于有局部解,相当于上司要走就派了两个小兵替他走 分治法的递归的拆解部分是包含divide——普通的拆解和conquer——合并结果——其实就是对在递归结果的基础上进行判断两部分的
独孤九剑
碰到二叉树的问题,就想想整棵树在该问题上的结果和左右子树在该问题上的结果之间 的联系是什么
分治法和遍历也可以同时使用
做算法题的时候先画图把思路想好再动笔
需要背的程序
1、preorder的迭代方式
public List<Integer> preorderTraversal(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<>();
LinkedList<Integer> output = new LinkedList<>();
if (root == null) {
return output;
}
stack.add(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pollLast();
output.add(node.val);
if (node.right != null) {
stack.add(node.right);
}
if (node.left != null) {
stack.add(node.left);
}
}
return output;
}
作者:LeetCode
2、inorder迭代方式
public List < Integer > inorderTraversal(TreeNode root) {
List < Integer > res = new ArrayList < > ();
Stack < TreeNode > stack = new Stack < > ();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
res.add(curr.val);
curr = curr.right;
}
return res;
}
作者:LeetCode