算法学习记录~2023.5.11~二叉树Day9~108.将有序数组转换为二叉搜索树 & 538.把二叉搜索树转换为累加树

前言


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

题目链接

力扣题目链接

思路

寻找数组的分割点,然后以分割点为当前节点,递归左区间和右区间。

还需要平衡,那自然就是左右两边的数尽可能相等,那么分割点就取中间值即可。

对于取中间值需要注意有可能right是最大int,那么用(left + right)/ 2 就会越界,因此可以用如下

int mid = left + ((right - left) / 2);

代码1:递归

class Solution {
public:
    TreeNode* traversal(vector<int>& nums, int left, int right){
        if (left > right)
            return NULL;
        int mid = left + ((right - left) / 2);
        TreeNode* node = new TreeNode(nums[mid]);
        node -> left = traversal(nums, left, mid-1);
        node -> right = traversal(nums, mid + 1, right);
        return node;
    }

    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.empty())
            return NULL;
        int left = 0;
        int right = nums.size() - 1;
        return traversal(nums, left, right);
    }
};

代码2:迭代

迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标,模拟的就是不断分割的过程

	关于处理左右区间的if后的条件怎么设置的?
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.size() == 0)
            return NULL;

        TreeNode* root = new TreeNode(0);       //初始化根结点
        queue<TreeNode*> nodeQue;                //存放遍历的节点
        queue<int> leftQue;                     //存放左区间下标
        queue<int> rightQue;                    //存放右区间下标
        nodeQue.push(root);                     //根节点入队列
        leftQue.push(0);                        //0为左区间下标初始位置
        rightQue.push(nums.size() - 1);         //nums.size() - 1为右区间下标初始位置
        while (!nodeQue.empty()){
            //取出三个队列里的元素
            TreeNode* cur = nodeQue.front();
            nodeQue.pop();
            int left = leftQue.front();
            leftQue.pop();
            int right = rightQue.front();
            rightQue.pop();

            int mid = left + ((right - left) / 2);
            cur->val = nums[mid];               //给中间节点赋值

            if (left <= mid - 1){               //处理左区间
                cur->left = new TreeNode(0);    //同样初始化下一层根结点
                nodeQue.push(cur->left);
                leftQue.push(left);
                rightQue.push(mid - 1);
            }

            if (right >= mid + 1) {             //处理右区间
                cur->right = new TreeNode(0);
                nodeQue.push(cur->right);
                leftQue.push(mid + 1);
                rightQue.push(right);
            }
        }
        return root;
    }
};

总结

思路较为简单,注意点第一个是关于取mid值时的溢出问题,另一个是处理左右区间的判断条件。
迭代法中处理左右区间的条件自己第一次思考没太想出来,下次注意


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

题目链接

力扣题目链接

思路

一开始容易忽略利用二叉搜索树的性质,直接累加节点地想非常麻烦,但是由于是二叉搜索树,因此按照题目要求的累加计算方式,就是转化为有序数组后,每个节点的值都替换为原来该值与之后所有值的和,也就是从后向前加。
正常情况使用前序遍历则得到从前往后的有序数组,那么从后往前就是右中左,也就是前序倒过来,接着按顺序累加即可

代码1:递归

class Solution {
public:
    int sum = 0;
    void traversal(TreeNode* cur){
        if (cur == NULL)
            return;
        traversal(cur->right);      //右
        sum += cur->val;            //中
        cur->val = sum;
        traversal(cur->left);       //左
    }

    TreeNode* convertBST(TreeNode* root) {
        traversal(root);
        return root;
    }
};

代码2:迭代

也就是中序模版题的改版

class Solution {
public:
    int sum = 0;
    TreeNode* convertBST(TreeNode* root) {
        stack<TreeNode*> st;            //用来处理节点上的元素
        TreeNode* cur = root;           //用来访问节点
        while (cur != NULL || !st.empty()){
            if (cur != NULL){
                st.push(cur);
                cur = cur->right;       //右
            }
            else{
                cur = st.top();         //中
                st.pop();
                sum += cur->val;
                cur->val = sum;
                cur = cur->left;        //左
            }
        }
        return root;
    }
};

总结


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,我们需要将按顺序存储在数组中的二叉树扩展为完全二叉树。可以通过添加 NULL 节点来实现扩展。然后,我们可以按照以下步骤将其转换为二叉链表形式: 1. 从根节点开始,将其左子节点设置为链表的下一个节点,将其右子节点设置为链表的下一个节点的右子节点。 2. 递归地将左子和右子转换为链表形式,并将它们连接到根节点的右子节点和左子节点的末尾。 以下是参考代码实现: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right # 扩展数组为完全二叉树 def completeTree(arr): n = len(arr) for i in range(n): if arr[i] is None: arr[i] = TreeNode() return arr # 将二叉树转换为链表形式 def flatten(root): if not root: return None left = root.left right = root.right # 将左子和右子转换为链表形式 left_last = flatten(left) right_last = flatten(right) # 将左子的末尾连接到右子的开头 if left_last: left_last.right = right root.right = left else: root.right = right # 将左子和右子都断开与根节点的连接 root.left = None root.right = None # 返回链表的末尾节点 if right_last: return right_last elif left_last: return left_last else: return root # 测试 arr = [1, 2, 3, 4, 5, None, 6] root = TreeNode(arr[0]) nodes = [root] for i in range(1, len(arr)): if arr[i]: node = TreeNode(arr[i]) parent = nodes[(i-1)//2] if i % 2 == 1: parent.left = node else: parent.right = node nodes.append(node) else: nodes.append(None) arr = completeTree(arr) flatten(root) while root: print(root.val, end=" ") root = root.right ``` 输出结果为:`1 2 4 5 3 6`,符合预期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山药泥拌饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值