学习笔记,总结labuladong公众号文章,方便自己以后更好的理解和学习!!!
是个人的学习笔记记录,是个人的学习笔记记录,是个人的学习笔记记录。
强烈推荐labuladong公众号进行学习
**二叉树遍历框架:**
void traverse(TreeNode root){
//前序遍历
traverse(root.left);
//中序遍历
traverse(root.right);
//后序遍历
}
重要性
1、快速排序和归并排序就是二叉树遍历的变形,快速排序是二叉树的前序遍历,归并排序是二叉树的后序遍历。
2、快速排序的算法思想:对num[lo,…,hi]排序,先找到一个分界点p,通过交换元素使得num[lo,…,p-1]都小于等于num[p],num[p+1,…,hi]的元素都大于num[p]。然后递归求num[lo,…,p-1]和num[p+1,…,hi]的分界点。
框架:
void sort(int[] num,int lo,int hi){
/********前序遍历的位置********/
//通过交换元素构建分界点p
int p=partition(nums,lo,hi);
/****************************/
sort(nums,lo,p-1);
sort(nums,p+1,hi);
}
(先构造分界点,然后去左右子数组构造分界点)
3、对num[lo,…,hi]进行归并排序,先对num[lo,…,mid]排序,再对num[mid+1,…,hi]排序,然后把这两个有序数列合并。
框架
void sort(int[] num,int lo,int hi){
int mid=(lo+hi)/2;
sort(num,lo,mid);
sort(num,mid+1,hi);
/********后序遍历位置********/
merge(num,lo,mid,hi);
}
(先对左右子数组排序,然后合并)
如何写递归
写递归算法的关键是要明确函数【定义】是什么,然后相信这个定义,利用这个定义推导最终结果,不要试图跳入递归。
写树相关的算法,简单来说,先搞清楚当前root节点该做什么,然后根据函数定义递归调用子结点。
题目
翻转二叉树(226)
代码:
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {val=x;}
}
class Solution{
public TreeNode inverTree(TreeNode root){
if(root==null) return null;
//交换根结点的左右子树
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
//向下递归左右子树
inverTree(root.left);
inverTree(root.right);
return root;
}
}
思路:
关键思路在于发现翻转整棵树就是交换每个结点的左右子结点,于是把交换左右子结点的代码放在前序遍历的位置。
二叉树题目的一个难点就在于如何把题目的要求细化为每个节点需要做的事情。
填充二叉树节点的右侧指针(116)
就是把二叉树每一层的节点用指针连接起来。
可以参照第一题的框架,但是会出现同一层父结点不相同的结点无法连接在一起。所以可以设置第二个函数连接两个节点。
//define for a Node
class Node{
public int val;
public Node left;
public Node right;
public Node next;
public Node(){}
public Node(int _val){
val=_val;
}
public Node(int _val,Node _right,Node _left, Node _next){
val=_val;
right=_right;left=_left;
next=_next;
}
};
class Solution{
public Node connect(Node root){
if(root==null) return null;
connectTwoNode(root.left,root.right);
return root;
}
public void connectTwoNode(Node node1,Node node2){
if(node1==null || node2==null) return;
node1.next=node2;
//相同父结点
connectTwoNode(node1.left,node1.right);
connectTwoNode(node2.left,node2.right);
//不同父结点
connectTwoNode(node1.right,node2.left);
}
}
二叉树展开为链表(114)
先将左右子树拉平成链,所以在后序遍历的位置。
//define for a binary tree node
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNde() {}
TreeNode(int val){
this.val=val;
}
TreeNode(int val,TreeNode left,TreeNode right){
this.val=val;
this.left=left;
this.right=right;
}
}
public Solution{
public void flatten(TreeNode root){
if(root==null) return;
flatten(root.left);
flatten(root.right);
//后序遍历位置
//1、将左右子树拉成链
TreeNode left=root.left;
TreeNode right=root.right;
//2、将左子树作为右子树
root.left=null;
root.right=left;
//3、将原先的右子树连接到当前的右子树的末端
TreeNode p=root;
while(p.right!=null){
p=p.right;
}
p.right=right;
}
}