Java-数据结构-二叉树<三>

news2024/11/15 12:41:49

承接上文:

Java-数据结构-二叉树<一>

Java-数据结构-二叉树<二>

一. 二叉树的简单介绍

        见Java-数据结构-二叉树<一>

二. 二叉树的典型代码实现

        见Java-数据结构-二叉树<一>

三. 二叉树的遍历

        见Java-数据结构-二叉树<一>

四. leetcode实战


1~11 见 Java-数据结构-二叉树<一>,<二>


12. leetcode 剑指 Offer 54. 二叉搜索树的第k大节点

        给定一棵二叉搜索树,请找出其中第 k 大的节点的值。
输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 4

【1】:

class Solution {
    int k;
    int ans;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return ans;
    }
    public void dfs(TreeNode root){
        if(root == null) return;
        dfs(root.right);
        k--;
        if(k == 0){
            ans =  root.val;
            return;
        }
        dfs(root.left);
    }
}

本题要点:(1)右根左

                  (2)变量提出来

                  (3)如果k放到参数中,每个递归函数中的 k 都是独立的(k 是数字,传入函数是值传递),这样的话只要回溯就会出错~


13. leetcode236 二叉树的最近公共祖先

        给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

        例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

 

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        if(q == root || p == root) return root;
        TreeNode left = lowestCommonAncestor(root.left, p,q);
        TreeNode right = lowestCommonAncestor(root.right, p,q);
        if(left == null && right != null) return right;
        if(left != null && right == null) return left;
        if(left != null && right != null) return root;
        return null;
    }
}

本题要点:

        退出条件
        1. root == null
        2. p,q中的任一一个为根节点
        单层逻辑

        1. 检查p,q能否在root.left中找到
        2. 检查p,q能否在root.right中找到
        3. 若1满足,2不满足,则最近公共节点为root.left
        4. 若1不满足,2满足,则最近公共节点为root.right
        5. 若1满足&2满足,则最近公共节点为root

14. leetcode653 两数之和 IV - 输入二叉搜索树

        给定一个二叉搜索树 root 和一个目标结果 k,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。

输入: root = [5,3,6,2,4,null,7], k = 9
输出: true

【2】:

class Solution {
    HashSet<Integer> set = new HashSet<>();
    public boolean findTarget(TreeNode root, int k) {
        if(root == null) return false;
        if(set.contains(k-root.val)) return true;
        set.add(root.val);
        return findTarget(root.left,k) || findTarget(root.right, k);
    }
    
}

本题要点:(1)用HashSet保存走过的路径的值,节省时间

15. leetcode102 二叉树的层序遍历

        给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        if(root == null) return list;
        Deque<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        while(!queue.isEmpty()){
            List<Integer> temp = new ArrayList<>();
            int len = queue.size();
            for(int i = 0; i < len; i++){
                root = queue.poll();
                temp.add(root.val);
                if(root.left != null){
                    queue.add(root.left);
                }
                if(root.right != null){
                    queue.add(root.right);
                }
            }
            list.add(temp);
        }
        return list;
    }
}

【X0】特别的:
BFS 遍历使用队列数据结构:

void bfs(TreeNode root) {
    Queue<TreeNode> queue = new ArrayDeque<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll(); // Java 的 pop 写作 poll()
        if (node.left != null) {
            queue.add(node.left);
        }
        if (node.right != null) {
            queue.add(node.right);
        }
    }
}

根据上述代码做出的结果是层序遍历是一维结构, 而层序遍历要求我们区分每一层,也就是返回一个二维数组。在每一层遍历开始前,先记录队列中的结点数量 n(也就是这一层的结点数量),然后一口气处理完这一层的 n 个结点。

// 二叉树的层序遍历
void bfs(TreeNode root) {
    Queue<TreeNode> queue = new ArrayDeque<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        int n = queue.size();
        for (int i = 0; i < n; i++) { 
            // 变量 i 无实际意义,只是为了循环 n 次
            TreeNode node = queue.poll();
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
    }
}

本题要点:(1)len的取值是为了知道上层有多少节点,用于分层

16. leetcode105 从前序与中序遍历序列构造二叉树

        给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

【C0】 :

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length < 1) return null;
        return helper(preorder,0,preorder.length,inorder,0,inorder.length);
    }
    public TreeNode helper(int[] preorder,int pleft, int pright, int[] inorder, int ileft, int iright){
        //左实右虚 到终点返回null
        if(pleft == pright){
            return null;
        }
        //构建根节点,根据前序遍历,根节点就是前序遍历的左边的元素
        TreeNode root = new TreeNode(preorder[pleft]);
        //用index来遍历在中序中的位置 找到对应的和前序最左节点的元素
        int index = 0;
        //index代表inorder中根节点的位置
        for(int i = ileft; i < iright; i++){
            if(preorder[pleft] == inorder[i]){
                index = i;
                break;
            }
        }
        // leftnum代表左子树的长度
        int leftnum = index - ileft;
        //递归建立左子树
        root.left = helper(preorder,pleft+1,pleft+leftnum+1,inorder,ileft,index);
        //递归建立左子树
        root.right = helper(preorder,pleft+leftnum+1,pright,inorder,index+1,iright);
        return root;
    }
}
// 前序 根 左 右
// 中序 左 根 右

本题要点:(1)在此种方法中,最重要的是找到根据前序遍历找到根节点的对应在中序遍历的位置,那么早在中序遍历中根节点左边为左子树,根节点右边为右子树

                  (2)接下来就要去寻找最为重要的左子树的起始和终点位置,右子树同理

                  (3)例如:

          10
        /    \
       8     12
      / \      /   \
     5   9  11  13
    / \
   3   6

前序遍历: [10,  8,5,3,6,9 , 12,11,13]
                      |    \______/     \____/   
                           左              右           

中序遍历: [3,6,5,9,8, 10,  11,13,12 ]
                    \______/    |      \____/   
                          左       根        右       
   

17. leetcode654 最大二叉树

        给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

        创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。返回 nums 构建的 最大二叉树 。

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。
    - [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
        - 空数组,无子节点。
        - [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。
            - 空数组,无子节点。
            - 只有一个元素,所以子节点是一个值为 1 的节点。
    - [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。
        - 只有一个元素,所以子节点是一个值为 0 的节点。
        - 空数组,无子节点。

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return createTreeNode(nums,0,nums.length-1);
    }
    public TreeNode createTreeNode(int[] nums, int left, int right){
        if(left > right){
            return null;
        }
        int max = nums[left];
        int index = left;
        for(int i = left; i <= right; i++){
            if(nums[i] > max){
                max = nums[i];
                index = i;
            }
        }
        TreeNode mid = new TreeNode(max);
        mid.left = createTreeNode(nums,left,index-1);
        mid.right = createTreeNode(nums,index+1,right);
        return mid;
    }
}

本题要点:(1)在一段递归中,找到限定区间内的最大值,即是root节点

                  (2)形成root节点对应的位置为分界点,左半边的最大值是左子节点,右半边的最大值是右子节点。

                  (3)此题需要left>right,否则叶子节点的子节点构建不成功

18. leetcode96 不同的二叉搜索树

        给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

输入:n = 3
输出:5

class Solution {
    public int numTrees(int n) {
        if(n == 0 || n == 1) return 1;
        int sum = 0;
        for(int i = 1; i <= n; i++){
            int left = numTrees(i-1);
            int right = numTrees(n-i);
            sum += left*right;
        } 
        return sum;
    }
}

动态规划版 

class Solution {
   public int numTrees(int n) {
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1; 
        for(int i = 2; i <= n; i++){
            for(int j = 1; j<= i; j++){
                dp[i] += dp[j-1]*dp[i-j];
            }
        } 
        return dp[n];
    }
}

本题要点:(1)在一次遍历中,走到第i个,那么第i个就是根节点

                  (2)处理根节点的左半边,就是i-1个,处理根节点的右半边就是n-(i-1)-1个

                  (3)处理顺序 [1,2,3,4,5,  6,     7,8, 9]
                                               \______/    |      \____/   
                                                    左        根(i)     右       
 

19. leetcode95 不同的二叉搜索树 II

        给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。

 输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]

【C1】:

class Solution {
    public List<TreeNode> generateTrees(int n) {
        if(n < 1)
            return new ArrayList<>();
        return helper(1, n);
    }

    public List<TreeNode> helper(int start, int end){
        List<TreeNode> list = new ArrayList<>();

        if(start > end){
            // 如果一颗树的左子树为空,右子树不为空,要正确构建所有树,
            // 依赖于对左右子树列表的遍历,也就是下面两层for循环的地方,
            // 如果其中一个列表为空,那么循环都将无法进行。

            list.add(null);
            return list;
        }

        for(int i = start; i <= end; i++){
            // TreeNode root = new TreeNode(i);
            //这行代码放置在注释的地方,会造成一个问题,就是以当前为root根结点的树个数就
            //num = left.size() * right.size() > 1时,num棵子树会共用这个root结点,
            //在下面两层for循环中,root的左右子树一直在更新,如果每次不新建一个root,
            //就会导致num个root为根节点的树都相同。

            List<TreeNode> left = helper(start, i-1);  
            List<TreeNode> right = helper(i+1, end); 

            // 固定左孩子,遍历右孩子
            for(TreeNode l : left){
                for(TreeNode r : right){
                    TreeNode root = new TreeNode(i);
                    root.left = l;
                    root.right = r;
                    list.add(root);
                }
            }
        }
        return list;
    }
}

本题要点:(1)如何处理左右节点,即找到根节点,建立根节点,如何将根节点和左右节点连接在一起,接着,如何只添加一棵树的根节点。

                  (2)递归构建左子树,并拿到左子树所有可能的根结点列表left,右树相同

                  (3)左右子树都是各不相同的,因为根结点不同,固定左子节点,遍历右半边 

20. leetcode515 在每个树行中找最大值

        给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> queue = new ArrayDeque<>();
        if(root != null){
            queue.add(root);
        }
        while(!queue.isEmpty()){
            List<Integer> list = new ArrayList<>();
            int n = queue.size();
            int max = Integer.MIN_VALUE;
            for(int i = 0; i < n; i++){
                TreeNode node = queue.poll();
                max = Math.max(max,node.val);
                if(node.left != null){
                    queue.add(node.left);  
                }
                if(node.right != null){
                    queue.add(node.right);
                }
            }
            ans.add(max);
        }
        return ans;
    }
}

本题要点:(1)此题的本质是二叉树的层序遍历,是15题的应用

                  (2)在每一层保存一个最值,初始化为Integer.MIN_VALUE,依次更新,最后添加到最后的答案中

21.  leetcode 剑指 Offer 33. 二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。

参考以下这颗二叉搜索树:

     5
    / \
   2   6
  / \
 1   3

示例 1:

输入: [1,6,3,2,5]
输出: false
示例 2:

输入: [1,3,2,6,5]
输出: true

【X1】:

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return recur(postorder,0,postorder.length-1);
    }
    public boolean recur(int[] postorder, int left, int right){
        if(left >= right) return true;
        int mid = left;
        while(postorder[mid] < postorder[right]) mid++;
        int cur = mid;
        while(cur < right){
            if(postorder[cur] < postorder[right]){
                return false;
            }
            cur++;
        }
        return recur(postorder,left,mid-1) && recur(postorder,mid,right-1);
    }
}

特别的 【X2】:

先看一下一颗二叉树:

     根
    /  \
   左   右

中序遍历:左->根->右
后序遍历:左->右->根

只要是二叉搜索树就一定就满足:
左 < 根 && 右 > 根

在后序遍历也是要满足该特性。那么只要在 后序遍历 中找到对应的 根 左 右 三个节点来对比是否满足就行。

如:

          10
        /    \
       8     12
      / \      /   \
     5   9  11  13
    / \
   3   6

后序遍历: [3,6,5,9,8, 11,13,12, 10]
                    \______/   \____/      |
                          左           右        根    

如果 左 < 根 && 右 > 根 成立。那么就有:

左集里面的每一个节点值都 小于 根
右集里面的每一个节点值都 大于 根

本题要点:(1)在规定范围区间内,最右边即是根节点

                  (2)第一个大于等于根节点(最右端节点)即为左半树

                  (3)验证在右半树中全部的元素都大于根节点(最右端节点)

                       

参考来源:【1】leetcode 育树霖疯 二叉树的最近公共祖先(Java视频讲解)

                  【2】leetcode 宫水三叶  一题双解:「哈希表+树的搜索」&「双指针 + BST 中序遍历」

                  【C0】leetcode windliang 详细通俗的思路分析,多解法

                  【C1】leetcode Krains 从构建单棵树到构建所有树,清晰易懂的递归思路。 

                  【X0】leetcode nettee  BFS 的使用场景总结:层序遍历、最短路径问题

                  【X1】leetcode 数据结构和算法 递归和栈两种方式解决,最好的击败了100%的用户 

                  【X2】leetcode 疯子 2种解法,清晰逻辑,秒懂--[Offer 33]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4. RNN网络架构解读|词向量模型|模型整体框架|训练数据构建|CBOW和Skip-gram模型|负采样方案

文章目录RNN网络架构解读词向量模型模型整体框架训练数据构建CBOW和Skip-gram模型负采样方案RNN网络架构解读 递归神经网络实际上就是普通的神经网络的部分进行修改更新&#xff1a;实际上常用于时间序列的更新。或者就是自然处理中 X序列代表着时间序列&#xff0c;x0是一个时…

linux入门---云服务器购买和登陆

目录标题云服务器选择云服务器购买xshell下载如何登陆云服务器Linux的新建与删除新建删除云服务器选择 学习linux的时候云服务器是一个非常重要的工具&#xff0c;那么我们在购买云服务器的时候有很多选择比如说&#xff1a;华为云&#xff0c;腾讯云&#xff0c;阿里云等等&a…

【实操案例十二】类和对象 实例代码及运行效果图!

任务一&#xff1a;定义一个圆的类&#xff0c;计算面积和周长 # 任务一&#xff1a;定义一个圆的类&#xff0c;计算面积和周长 import math class Circle():def __init__(self,r):self.rrdef get_area(self):return math.pi*r*rdef get_perimeter(self):return 2*math.pi*r …

初识 ThreeJS (ThreeJS 相关环境搭建)

初识 ThreeJS &#xff08;初识 ThreeJS &#xff08;ThreeJS 相关环境搭建&#xff09;参考描述ThreeJS在本地搭建 NodeJS 的官方网站获取使用安装依赖项运行官方文档案例场景编辑器搭建 ThreeJS 运行环境webpack项目结构package.jsonwebpack.config.js深入获取检测参考 项目…

袋式除尘器—分类和命名

按除尘器的结构形式分类(1)按滤袋开头分类按滤袋形状分类&#xff0c;可分为圆袋式除尘器和扁袋式除尘器两类。①圆袋式除尘器。滤袋形状为圆筒形&#xff0c;直径一般为120&#xff5e;300mm&#xff0c;最大不超过600mm&#xff1b;高度为2&#xff5e;3m&#xff0c;也有10m…

redis 数据库简介

一 概述 redis是一种nosql数据库,他的数据是保存在内存中&#xff0c;同时redis可以定时把内存数据同步到磁盘&#xff0c;即可以将数据持久化&#xff0c;并且他比memcached支持更多的数据结构(string,list列表[队列和栈],set[集合],sorted set[有序集合],hash(hash表))。相关…

2023年哪款手机浏览器比较好用,最后一个吹爆它

很多人不满足于手机自带的浏览器&#xff0c;为了更好地满足看视频、浏览网页、看小说等需求&#xff0c;不少人下载第三方手机浏览器来使用。我们都知道&#xff0c;手机浏览器是手机不可缺少的APP之一。那么&#xff0c;2023年哪款手机浏览器比较好用&#xff1f;下面分享今年…

Java File类及案例

File概述和构造方法 File对象就表示一个路径&#xff0c;可以是文件路径、也可以是文件夹的路径这个路径可以是存在的&#xff0c;也允许是不存在的 方法名称说明public File (String pathname)把字符串表示的路径变成File对象public File (Srting parent, String child)把父…

【My Electronic Notes系列——三极管】

目录 序言&#xff1a; &#x1f3ee;&#x1f3ee;新年的钟声响&#xff0c;新年的脚步迈&#xff0c;祝新年的钟声&#xff0c;敲响你心中快乐的音符&#xff0c;幸运与平安&#xff0c;如春天的脚步紧紧相随&#xff0c;春节快乐&#xff01;春华秋实&#xff0c;我永远与你…

C语言入门(八)——数组

数组的基本概念 数组应用实例:统计随机数 数组应用实例:直方图 字符串 多维数组 数组的基本概念 数组(Array)也是一种复合数据类型&#xff0c;它由一系列相同类型的元素(Element)组成。例如定义一个由4个int型元素组成的数组count: int count[4]; 和结构体成员类似&…

安卓S开机动画流程

安卓S开机动画流程 开机动画是在SurfaceFlinger实例通过调用startBootAnim()启动的&#xff0c;BootAnim是如何启动和结束的&#xff0c;总体框架图如下&#xff1a; 1.SurfaceFlinger进程启动 # /frameworks/native/services/surfaceflinger/surfaceflinger.rc service surf…

linux inode详解

1.inode 和 block 概述. 操作系统的文件数据除了实际内容之外&#xff0c;通常含有非常多的属性&#xff0c;例如Linux操作系统的文件权限与文件属性。文件系统通常会将这两部分内容分别存放在inode和block中。 文件是存储在硬盘上的&#xff0c;硬盘的最小存储单位叫做扇区sec…

行为型模式

1.模版方法 超类中定义了一个算法的框架&#xff0c; 允许子类在不修改结构的情况下重写算法的特定步骤 结构 抽象类&#xff1a;负责给出一个轮廓与骨架&#xff0c;由一个模版方法和若干个基本方法构成 模版方法&#xff1a;按某种顺序调用其包含的基本方法基本方法&#xf…

计算机视觉OpenCv学习系列:第八部分、图像操作-4

第八部分、图像操作-4第一节、图像卷积操作1.图像卷积定义2.卷积函数3.代码练习与测试第二节、高斯模糊1.高斯模糊2.函数解释3.代码练习与测试第三节、像素重映射1.像素重映射定义2.重映射函数3.代码练习与测试学习参考第一节、图像卷积操作 1.图像卷积定义 卷积的基本原理&am…

java spring IOC xml 方式 内部Bean注入

上次说了外部 Bean注入 这次来演示一个内部的 Bean注入 我们先创建一个spring 项目 导入最基本的 spring 包 在项目src目录下创建一个包 cascade cascade包下创建两个类 Dept 部门类 参考代码如下 package cascade;//部门类 public class Dept {private String dname;publi…

windows ssdt

前言 我们 ring 3 跳转 ring0 另一种方式使用sysenter命令。 sysenter 相比起jmp,int xx方式相比速度更快&#xff0c;因为sysenter指令大量的使用了MSR寄存器 存储跳转地址等。 MSR寄存器相关读/写命令 //读取msr寄存器 rdmsr xxxx //写入msr寄存器 wrmsr xxxx其中xxx是ms…

轻量实时操作系统学习(一)

306xH系列产品基于高性能RISC-V CPU核&#xff0c;工作频率最高到200MHz&#xff0c;集成了FPU浮点处理单元&#xff0c;支持浮点乘法&#xff0c;支持浮点乘法&#xff0c;除法和开方等复杂数学运算指令&#xff0c;支持16KB的SRAM和最高160KB的flash存储单元。 该MCU集成最多…

【My Electronic Notes系列——二极管】

目录 序言&#xff1a; &#x1f3ee;&#x1f3ee;新年的钟声响&#xff0c;新年的脚步迈&#xff0c;祝新年的钟声&#xff0c;敲响你心中快乐的音符&#xff0c;幸运与平安&#xff0c;如春天的脚步紧紧相随&#xff0c;春节快乐&#xff01;春华秋实&#xff0c;我永远与…

【目标检测论文解读复现NO.25】基于改进Yolov5的地铁隧道附属设施与衬砌表观病害检测方法

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…

【Unity Shader 赛博小人01】UV准备 SD制作特效贴图

写在前面 Unity 卡通渲染 程序化天空盒提到了——“再整个uv1将云片平铺&#xff0c;将uv1对应到世界坐标x轴旋转角、y轴旋转角&#xff0c;消散信息放到顶点色。”&#xff0c;就是这句话&#xff01;我又遇到了几个问题&#xff08;本菜鸡不知道的东西太多太多了&#xff09…