代码随想录算法训练营第二十三天 |LC 669. 修剪二叉搜索树、LC 108. 将有序数组转换为二叉搜索树、LC 538. 把二叉搜索树转换为累加树、总结

669. 修剪二叉搜索树

思路

  1. 截止条件:为空节点
  2. 单层递归:值如果小于low,值如果大于high,如果值在lowhigh之间,则递归左右节点
  3. 返回:返回根节点

代码

  1. 递归
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (!root) return nullptr;
        if (root->val < low) 
            return trimBST(root->right, low, high);
        if (root->val > high) 
            return trimBST(root->left, low, high); 
        if (root->val >= low && root->val <= high){
            root->left = trimBST(root->left, low, high);
            root->right = trimBST(root->right, low, high);
        }
        return root;
    }
};
  1. 迭代
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (!root) return nullptr;

        while (root != nullptr && (root->val < low || root->val > high)) {
            if (root->val < low) root = root->right; 
            else root = root->left;
        } // 找到在范围中的根节点

        auto cur = root;
        while (cur){
            while (cur->left && cur->left->val < low){
                cur->left = cur->left->right;
            }
            cur = cur->left;
        } // 找寻符合要求的左子树

        cur = root;
        while (cur){
            while (cur->right && cur->right->val > high){
                cur->right = cur->right->left;
            }
            cur = cur->right;
        }//找寻符合要求的右子树

        return root;
    }
};

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

思路

  1. 有序数组,中间对半分,左侧一直向左,右侧一直向右
  2. 有序数组,中间对半分,每次都递归左侧这部分作为左子树再构建,右侧作为右子树再构建一个,注意截止条件

代码

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return dfs(nums, 0, nums.size() - 1);
    }
    TreeNode* dfs(vector<int>& nums, int left, int right){
        if (left > right) return nullptr;
        int mid = (left + right) >> 1;
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = dfs(nums, left, mid - 1);
        root->right = dfs(nums, mid + 1, right);
        return root;
    }
};

538. 把二叉搜索树转换为累加树

思路

  1. 第一次中序遍历记录sum总和,第二次中序遍历更改val
  2. 右中左

代码

class Solution {
public:
    vector<int> a;
    int sum = 0;
    int cur = 0;
    TreeNode* convertBST(TreeNode* root) {
        dfs(root);
        return dfs1(root);
    }
    void dfs(TreeNode* root){
        if (!root) return;
        dfs(root->left);
        a.push_back(root->val);
        sum += root->val;
        dfs(root->right);
        return;
    }
    TreeNode* dfs1(TreeNode* root){
        if (!root) return nullptr;
        dfs1(root->left);
        cur = root->val;
        root->val = sum;
        sum -= cur;
        dfs1(root->right);
        return root;
    }
};
  1. 迭代
class Solution {
public:
    int pre = 0;
    TreeNode* convertBST(TreeNode* root) {
        if (!root) return nullptr;
        stack<TreeNode*> stk;
        auto cur = root;
        while (!stk.empty() || cur != nullptr){
            if (cur){
                stk.push(cur);
                cur = cur->right;
            }else{
                cur = stk.top();
                stk.pop();
                cur->val += pre;
                pre = cur->val;
                cur = cur->left;
            }
        }
        return root;
    }
};

总结

总结链接

遍历方式

前中后序 层序,迭代+递归

性质

  1. 二叉树:是否对称
    递归:后序,比较的是根节点的左子树与右子树是不是相互翻转
    迭代:使用队列/栈将两个节点顺序放入容器中进行比较
  2. 二叉树:求最大深度
    递归:后序,求根节点最大高度就是最大深度,通过递归函数的返回值做计算树的高度
    迭代:层序遍历
  3. 二叉树:求最小深度
    递归:后序,求根节点最小高度就是最小深度,注意最小深度的定义
    迭代:层序遍历
  4. 二叉树:求有多少个节点
    递归:后序,通过递归函数的返回值计算节点数量
    迭代:层序遍历
  5. 二叉树:是否平衡
    递归:后序,注意后序求高度和前序求深度,递归过程判断高度差
    迭代:效率很低,不推荐
  6. 二叉树:找所有路径
    递归:前序,方便让父节点指向子节点,涉及回溯处理根节点到叶子的所有路径
    迭代:一个栈模拟递归,一个栈来存放对应的遍历路径
  7. 二叉树:递归中如何隐藏着回溯
  8. 二叉树:求左叶子之和
    递归:后序,必须三层约束条件,才能判断是否是左叶子。
    迭代:直接模拟后序遍历
  9. 二叉树:求左下角的值(opens new window)
    递归:顺序无所谓,优先左孩子搜索,同时找深度最大的叶子节点。
    迭代:层序遍历找最后一行最左边
  10. 二叉树:求路径总和
    递归:顺序无所谓,递归函数返回值为bool类型是为了搜索一条边,没有返回值是搜索整棵树。
    迭代:栈里元素不仅要记录节点指针,还要记录从头结点到该节点的路径数值总和
    ………………
第二十二算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值