347. 前 K 个高频元素,二叉树的递归遍历,二叉树的迭代遍历

347. 前 K 个高频元素

题目链接:https://programmercarl.com/0347.%E5%89%8DK%E4%B8%AA%E9%AB%98%E9%A2%91%E5%85%83%E7%B4%A0.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

思路

  1. 小根堆–用优先队列PriorityQueue实现

语法

  • 优先队列PriorityQueue
    1. 因为要比较的是频次,所以要在小根堆里保存数组int[];pair2[1]-pair1[1]大根堆,pair1[1]-pair2[1]小根堆PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2)->pair2[1]-pair1[1]);
    2. 添加:add(),删除:poll()
    3. 因为堆里保存的是int[],所以add的是new int[]{key,value}
  • hashmap:
    1. map注意是保存两个值 Map<Integer,Integer> map = new HashMap<>();
    2. 遍历:
      • key和value:for(Map.Entry<Integer,Integer> en:map.entrySet()):
      • key:for(Integer key : map.keySet()):
  • 泛型参数:
    1. 泛型参数必须是引用类型,而原始类型不是引用类型。
    2. int[]是引用类型

二叉树的递归遍历

题目链接:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%80%92%E5%BD%92%E9%81%8D%E5%8E%86.html#%E6%80%9D%E8%B7%AF

  1. 因为要打印出前序遍历节点的数值,所以参数里需要传入数组来放节点的数值,除了这一点就不需要再处理什么数据了也不需要有返回值,所以递归函数返回类型就是void
  2. 确定终止条件:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要结束了,所以如果当前遍历的这个节点是空,就直接return
  3. 确定单层递归的逻辑

二叉树的非递归遍历

题目链接:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%BF%AD%E4%BB%A3%E9%81%8D%E5%8E%86.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
算法参考:https://blog.csdn.net/Monster_ii/article/details/82115772

前序遍历

思路:从root开始遍历左子树,全部依次压栈,左子树遍历完,开始自下至上遍历右子树。

在前序访问中,栈中元素都是自己和自己的左孩子都访问过了,而右孩子还没有访问到的节点。

伪代码:

TreeNode cur=root;
while(cur!=null||!st.empty()){
	while(cur!=null){
		访问cur(打印或者添加数组);
		st.push(cur);当前节点压栈
		cur=cur.left;遍历左孩子
	}
	cur=st.pop();栈顶是最左的节点
	cur=cur.right;左子树遍历完,遍历右子树
}

完整代码:

public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans=new ArrayList<>();
        Stack<TreeNode> st=new Stack<>();
        TreeNode cur=root;
        while(cur!=null||!st.empty()){
            while(cur!=null){
                ans.add(cur.val);
                st.push(cur);
                cur=cur.left;
            }
            cur=st.pop();

            cur=cur.right;
        }

        return ans;
    }

中序遍历

思路:和前序类似,从root开始遍历左子树,全部依次压栈,左子树遍历完,开始自下至上遍历右子树。

在中序访问中,栈中元素都是自己和自己的左孩子,但都还没访问,右孩子也没有访问到的节点。

伪代码:

TreeNode cur=root;
while(cur!=null||!st.empty()){
	while(cur!=null){
		st.push(cur);当前节点压栈
		cur=cur.left;遍历左孩子
	}
	cur=st.pop();栈顶是最左的节点
	访问cur节点
	cur=cur.right;左子树遍历完,遍历右子树
}

完整代码:

    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans=new ArrayList<>();
        Stack<TreeNode>st=new Stack<>();
        TreeNode cur=root;
        while(cur!=null||!st.empty()){
            while(cur!=null){
                st.push(cur);
                cur=cur.left;
            }
            cur=st.pop();
            ans.add(cur.val);
            cur=cur.right;
        }
        return ans;
    }

后序遍历

思路:和前序类似,从root开始遍历左子树,全部依次压栈,左子树遍历完,开始自下至上遍历右子树。但多了top指针和last指针。top是栈顶节点,last是上一个存放的节点。
因为后序遍历,所以先左子树,再右子树,再中间节点。

怎么判断top为中间节点?应该判断top的右节点是last,即中间节点的右子树刚刚遍历完毕。

伪代码:

TreeNode cur=root;
while(cur!=null||!st.empty()){
	while(cur!=null){
		st.push(cur);当前节点压栈
		cur=cur.left;遍历左孩子
	}
	top=st.peek();栈顶是最左的节点
	if(top没有右子树||top的右节点遍历过了(top是父节点)){
		st.pop();
		访问top
		last=top;
	}
	else{
		cur=top.right;左子树遍历完,遍历右子树
	}
	
}

完整代码:

    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ans=new ArrayList<>();
        Stack<TreeNode>st=new Stack<>();
        TreeNode cur=root,last=null,top=null;
        while(cur!=null||!st.empty()){
            while(cur!=null){
                st.push(cur);
                cur=cur.left;
            }
            top=st.peek();
            if(top.right==null||top.right==last){
                ans.add(top.val);
                last=top;
                st.pop();
            }else{
                cur=top.right;
            }
        }
        return ans;
    }
  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值