20天 hot 100 速通计划-day09

发布时间 2023-08-15 15:37:51作者: Ba11ooner

二叉树

102. 二叉树的层序遍历

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

示例 1:

img

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

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000]
  • -1000 <= Node.val <= 1000

纯技巧原子操作,本质上就是栈的应用,属于二叉树中少见的非递归处理方法

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
      //用于记录多层遍历结果
        vector<vector<int>> res;
      
      //剪枝:空树直接不处理
        if(root==nullptr) return res;
      
      //处理工具:栈
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
          //用于记录单层遍历结果
            vector<int> level;
          //会变,所以单独设置为 size,实时更新
            int size = q.size();
            for(int i = 0; i < size; i++){
              //注意:front() 只取值,不弹出,需要之后额外调用 pop() 弹出
                TreeNode* cur = q.front();
              //注意:front() 只弹出,不取值,需要之前额外调用 front() 取值
                q.pop();
              //单层结果记录  
                level.push_back(cur->val);
              //下一层入栈
                if(cur->left!=nullptr){
                    q.push(cur->left);
                }
                if(cur->right!=nullptr){
                    q.push(cur->right);
                }
            }
          //多层结果记录
            res.push_back(level);
        }
        return res;
    }
}

108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例 1:

img

输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

img

输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums严格递增 顺序排列

原子操作

class Solution {
public:  
  TreeNode* sortedArrayToBST(vector<int>& nums) {
        return buildBST(nums, 0, nums.size() - 1);
    }
    
  //参返分析:输入有序数组,左右子树的值,输出二叉搜索树
  //终止条件:左 > 右
  //单层逻辑:二分法,中间作为根节点,一半作为左子树,一半作为右子树
    TreeNode* buildBST(vector<int>& nums, int left, int right) {
        if (left > right) {
            return nullptr;
        }
        
      //减法求中点,防溢出
        int mid = left + (right - left) / 2;
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = buildBST(nums, left, mid - 1);
        root->right = buildBST(nums, mid + 1, right);
        
        return root;
    }
};

98. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

img

输入:root = [2,1,3]
输出:true

示例 2:

img

输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示:

  • 树中节点数目范围在[1, 104]
  • -231 <= Node.val <= 231 - 1

原子操作

class Solution {
public:
    long pre = LONG_MIN;
    //关键:中序遍历得升序数组,魔改中序遍历即可判断

    //参返分析:输入根节点,输出判断结果
    //终止条件:当前节点为空,直接返回 true
    //单层逻辑:魔改中序遍历,判断左子树,处理根节点(更新 pre),判断右子树
    bool func(TreeNode* root){
        if(!root) return true;
        
        // 访问左子树
        if(!isValidBST(root->left)) return false;

        // 访问当前节点
        //如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
        if(root->val <= pre) return false;
        pre = root->val;

        // 访问右子树
        return isValidBST(root->right);
    }
    bool isValidBST(TreeNode* root) {
        return func(root);
    }
};

230. 二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

示例 1:

img

输入:root = [3,1,4,null,2], k = 1
输出:1

示例 2:

img

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

提示:

  • 树中的节点数为 n
  • 1 <= k <= n <= 104
  • 0 <= Node.val <= 104
class Solution {
public:
  //关键:中序遍历得递增数组
  //先中序遍历,再取第k个元素(下标 k-1)
  void inorderTraversal(TreeNode* root, vector<int>& nodes) {
      if (root == nullptr) {
          return;
      }
      inorderTraversal(root->left, nodes);
      nodes.push_back(root->val);
      inorderTraversal(root->right, nodes);
  }

  int kthSmallest(TreeNode* root, int k) {
      vector<int> nodes;
      inorderTraversal(root, nodes);
      return nodes[k-1];
  }
}

199. 二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例 1:

img

输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

示例 2:

输入: [1,null,3]
输出: [1,3]

示例 3:

输入: []
输出: []

提示:

  • 二叉树的节点个数的范围是 [0,100]
  • -100 <= Node.val <= 100
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        if (root == nullptr) {
            return result;
        }
        
        queue<TreeNode*> q;
        q.push(root);
        
        while (!q.empty()) {
            int size = q.size();
        //与纯粹层序遍历不同,此处没有引入记录单层数值的 level 数组
        //vector<int> level;
            for (int i = 0; i < size; i++) {
                TreeNode* node = q.front();
                q.pop();
                
            //与纯粹层序遍历不同,此处只在 i 为最右侧节点时记录值
            //level.push_back(node->val);
                if (i == size - 1) {
                    result.push_back(node->val);
                }
                
                if (node->left != nullptr) {
                    q.push(node->left);
                }
                if (node->right != nullptr) {
                    q.push(node->right);
                }
            }
        //与纯粹层序遍历不同,此处没有引入记录多层数值的 res 数组,也不按层记录
        //res.push_back(level);
        }
        return result;
    }
};