leetcode Recover Binary Search Tree

本文讨论了如何在不改变二叉搜索树结构的情况下修复因错误交换两个元素导致的问题,并提供了常数空间解决方案的实现。通过深入分析二叉树的中序遍历,找出并修复错误交换的节点。

 

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

 

Give an inorder traversal for the binary tree. 

 

Find the first node res1, which is larger than its successor. 

Find the first node p, which is larger than res1->val. So the predecessor of p is the second index we wanna find. 

However, in the recursive program, there are some mistake, here is wrong code: 

 

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
 public:
 
  TreeNode *last = NULL, *res1 = NULL, *res2 = NULL;
  void inorder(TreeNode* root) {
    if (root == NULL)
      return;
    if (res1 && res2)
      return;
    inorder(root->left);
    
    if (last != NULL && res1 == NULL && last->val > root->val) 
      res1 = last;
    else if (last != NULL && res1 != NULL && root->val > res1->val) {
      res2 = last;
      swap(res1->val, last->val);
      return;  
    }
    last = root;
    
    inorder(root->right);
  }
  
  void recoverTree(TreeNode *root) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    last = res1 = res2 = NULL;
    inorder(root);
    if (res2 == NULL)
      swap(res1->val, last->val);
    //if (res1 && res2)
    //  swap(res1->val, res2->val);
    
  }
};


The wrong case is :

 

 

Input:{10,5,15,0,8,13,20,2,-5,6,9,12,14,18,25}
Output:{10,5,15,0,8,13,20,2,-5,6,9,12,14,18,25}
Expected:{10,5,15,0,8,13,20,-5,2,6,9,12,14,18,25}

 

The reason is that the branch else if is executed more than once although returning. Take the WA case for example, after visiting 5, 8 is returned. But 10 is visited afterwards: TreeNode* last hasn't been updated, so swap the second time. The right code is: 

 

 

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
 public:
 
  TreeNode *last = NULL, *res1 = NULL, *res2 = NULL;
  void inorder(TreeNode* root) {
    if (root == NULL)
      return;
    if (res1 && res2)
      return;
    inorder(root->left);
    
    if (last != NULL && res1 == NULL && last->val > root->val) 
      res1 = last;
    else if (last != NULL && res1 != NULL && res2 ==NULL && root->val > res1->val) {
      res2 = last;
      swap(res1->val, last->val);
      return;  
    }
    last = root;
    
    inorder(root->right);
  }
  
  void recoverTree(TreeNode *root) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    last = res1 = res2 = NULL;
    inorder(root);
    if (res2 == NULL)
      swap(res1->val, last->val);
    //if (res1 && res2)
    //  swap(res1->val, res2->val);
    
  }
};

Python Version:

class Solution:
    def recoverTree(self, root):
        prev,cur,last = None,root,None
        stack,wrongPairs = [],[]
        while (cur != None or stack):
            while (cur != None):
                stack.append(cur)
                cur = cur.left
            if (stack):
                cur = stack.pop()
                if (prev != None and prev.val > cur.val):
                    wrongPairs.append([prev,cur])
                last,prev = cur,cur
                cur = cur.right
        if (len(wrongPairs) > 1):
            wrongPairs[0][0].val,wrongPairs[1][1].val=wrongPairs[1][1].val,wrongPairs[0][0].val
        elif (len(wrongPairs) == 1):
            wrongPairs[0][0].val,wrongPairs[0][1].val=wrongPairs[0][1].val,wrongPairs[0][0].val

 

 

 

 

内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
数字图像隐写术是一种将秘密信息嵌入到数字图像中的技术,它通过利用人类视觉系统的局限性,在保持图像视觉质量的同时隐藏信息。这项技术广泛应用于信息安全、数字水印和隐蔽通信等领域。 典型隐写技术主要分为以下几类: 空间域隐写:直接在图像的像素值中进行修改,例如LSB(最低有效位)替换方法。这种技术简单易行,但对图像处理操作敏感,容易被检测到。 变换域隐写:先将图像转换到频域(如DCT或DWT域),然后在变换系数中嵌入信息。这类方法通常具有更好的鲁棒性,能抵抗一定程度的图像处理操作。 自适应隐写:根据图像的局部特性动态调整嵌入策略,使得隐写痕迹更加分散和自然,提高了安全性。 隐写分析技术则致力于检测图像中是否存在隐藏信息,主要包括以下方法: 统计分析方法:检测图像统计特性的异常,如直方图分析、卡方检测等。 机器学习方法:利用分类器(如SVM、CNN)学习隐写图像的区分特征。 深度学习方法:通过深度神经网络自动提取隐写相关特征,实现端到端的检测。 信息提取过程需要密钥或特定算法,通常包括定位嵌入位置、提取比特流和重组信息等步骤。有效的隐写系统需要在容量、不可见性和鲁棒性之间取得平衡。 随着深度学习的发展,隐写与反隐写的技术对抗正在不断升级,推动了这一领域的持续创新。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值