Leetcode二叉树算法个人理解

二叉树的前中后序遍历递归写法

树节点

class TreeNode {

int val;

TreeNode left;

TreeNode right;

TreeNode(int val) { this.val = val; }

}

前序

class Solution {

public List preorderTraversal(TreeNode root) {

List res = new ArrayList<>();

dfs(root, res);

return res;

}

private void dfs(TreeNode node, List res) {

if (node == null) return;

res.add(node.val); // 根

dfs(node.left, res); // 左

dfs(node.right, res); // 右

}

}

中序:

class Solution {

public List inorderTraversal(TreeNode root) {

List res = new ArrayList<>();

dfs(root, res);

return res;

}

private void dfs(TreeNode node, List res) {

if (node == null) return;

dfs(node.left, res); // 左

res.add(node.val); // 根

dfs(node.right, res); // 右

}

}

栈写法:

class Solution {

public List inorderTraversal(TreeNode root) {

List res = new ArrayList<>();

Deque stack = new ArrayDeque<>();

TreeNode cur = root;

复制代码
    while (cur != null || !stack.isEmpty()) {
        // 1. 一直向左走,把所有左边界压入栈
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
        // 2. 弹出栈顶(此时是最左的节点)
        cur = stack.pop();
        res.add(cur.val); // 访问
        
        // 3. 转向右子树(如果有右孩子,下次循环会继续处理右孩子的左边界)
        cur = cur.right;
    }
    return res;
}

}

后序:

class Solution {

public List postorderTraversal(TreeNode root) {

List res = new ArrayList<>();

dfs(root, res);

return res;

}

private void dfs(TreeNode node, List res) {

if (node == null) return;

dfs(node.left, res); // 左

dfs(node.right, res); // 右

res.add(node.val); // 根

}

}

判断是否是二叉搜索树

思路:转化为 中序遍历+是否是递增数组判断

/**

* Definition for a binary tree node.

* public class TreeNode {

* int val;

* TreeNode left;

* TreeNode right;

* TreeNode() {}

* TreeNode(int val) { this.val = val; }

* TreeNode(int val, TreeNode left, TreeNode right) {

* this.val = val;

* this.left = left;

* this.right = right;

* }

* }

*/

class Solution {

public void dfs(TreeNode node,List res){

if(node==null)return;

dfs(node.left,res);

res.add(node.val);

dfs(node.right,res);

}

public boolean isValidBST(TreeNode root) {

List res=new ArrayList<>();

dfs(root,res);

for(int i=1;i<res.size();i++){

if(res.get(i)<=res.get(i-1))return false;

}

return true;

}

}

1. 数组(Array)
  • 取值:arr[i]

  • 长度:arr.length (注意:没有括号,是一个属性)

2. 列表(List / ArrayList / LinkedList)
  • 取值:list.get(i) (⚠️ 这就是你刚才写错的地方)

  • 长度:list.size() (注意:有括号,是一个方法)

3. 映射(Map / HashMap)
  • 取值:map.get(key) (它不用数字索引,而是用键去取)

  • 长度:map.size()

4. 字符串(String)
  • 取某个字符:str.charAt(i)

  • 长度:str.length()

5. 栈(Stack / Deque 作为栈用)
  • 取值(只看不取):stack.peek()

  • 取值(弹出):stack.pop()

二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 **先序遍历** 顺序相同。

思路:利用递归进行先序遍历收集为一个列表,对于当前列表,原地修改指针指向

/**

* Definition for a binary tree node.

* public class TreeNode {

* int val;

* TreeNode left;

* TreeNode right;

* TreeNode() {}

* TreeNode(int val) { this.val = val; }

* TreeNode(int val, TreeNode left, TreeNode right) {

* this.val = val;

* this.left = left;

* this.right = right;

* }

* }

*/

class Solution {

public void dfs(TreeNode node,Listres){

if(node==null)return;

res.add(node);

dfs(node.left,res);

dfs(node.right,res);

}

public void flatten(TreeNode root) {

Listres=new ArrayList<>();

dfs(root,res);

for(int i=1;i<res.size();i++){

TreeNode pre=res.get(i-1);

TreeNode cur=res.get(i);

pre.left=null;

pre.right=cur;

}

}

}

思路2:原地翻转,不开List

  1. 遍历当前节点 cur。

  2. 如果 cur.left 不为空:

    • 找到 cur.left 这棵树的最右节点,记为 pre。

    • 将 cur.right 挂到 pre.right 上。

    • 将 cur.left 移到 cur.right 上。

    • 将 cur.left 置为 null。

  3. 移动到下一个节点:cur = cur.right。

    /**

* Definition for a binary tree node.

* public class TreeNode {

* int val;

* TreeNode left;

* TreeNode right;

* TreeNode() {}

* TreeNode(int val) { this.val = val; }

* TreeNode(int val, TreeNode left, TreeNode right) {

* this.val = val;

* this.left = left;

* this.right = right;

* }

* }

*/

class Solution {

public void flatten(TreeNode root) {

TreeNode cur=root;

while(cur!=null){

if(cur.left!=null){

TreeNode pre=cur.left;

while(pre.right!=null){

pre=pre.right;

}

pre.right=cur.right;

cur.right=cur.left;

cur.left=null;

}

cur=cur.right;

}

}

}

相关推荐
小oo呆1 小时前
【学习心得】MCP工具开发学习笔记
笔记·学习
kyrie_sakura1 小时前
大模型学习19 大模型学习 - LangChain2_Retrieval(RAG-文档处理-向量处理检索-Milvus)
学习·langchain·milvus
Rain的Java大神之路1 小时前
面试被LeetCode 27(移除元素)问懵?别再用两层 for 循环了:一道“简单题”吃透双指针原地删除,附面试加分话术 + 11 个避坑清单
后端·leetcode·面试
pjj198541 小时前
YOLO 目标检测算法系列梳理:从 V1 到 V5 的原理演进
算法·yolo·目标检测
2601_961146202 小时前
实验室用等离子表面处理设备处理汽车PP内饰件和PBT骨架的一点记录
笔记·汽车·设备
二十七日秋2 小时前
算法刷题笔记「Day 1|四道 OJ 入门题里的深坑」
c语言·汇编·数据结构·c++·笔记·python·算法
女神下凡2 小时前
芯参谋(79):嵌入式学习进阶_(硬件与软件)深入实践指南
arm开发·单片机·嵌入式硬件·学习·fpga开发·设计规范
星恒随风2 小时前
Linux Socket TCP编程(二):逐文件重构多进程、多线程与线程池服务器,深入fork、pthread_create、popen和std::bind
linux·服务器·笔记·学习·tcp/ip
晚风叙码2 小时前
Linux 进程概念(下):程序地址空间与虚拟内存
linux·服务器·算法