一、问题描述
第99题,题目链接:力扣https://leetcode.cn/problems/recover-binary-search-tree/
图1-1
如图1-1,二叉搜索树中“恰好”有两个节点的值被错误地交换,我们找到错误的节点,并恢复二叉搜索树。例如图中示例1,是错误节点交换前后的示例图。
二、技术路线
利用二叉树的中序遍历。
如果是一棵有效的二叉搜索树,那么这棵二叉搜索树的中序遍历结果是严格递增(满足nums[i] < nums[i+1])的。如果两个节点值被错误交换,那么这个中序遍历结果序列就不是递增的,这时可以根据是否满足nums[i] < nums[i+1],来找出这两个被错误交换节点的值。
具体流程如下。
1.中序遍历二叉树,得到的序列保存在nums中。
2.在nums中找到不满足特性nums[i] < nums[i+1]的节点值,并记录这两个值。
3.根据找到的两个值,恢复二叉搜索树。
三、代码实现
以下这段代码,是在学习官方提供的题解过程中完成的。
public:
void inorder(TreeNode *root, vector<int> &nums) {
if(root == nullptr) {
return;
}
inorder(root->left, nums);
nums.push_back(root->val);
inorder(root->right, nums);
}
pair<int, int> findTwoSwapper(vector<int> &nums) {
int x = -1, y = -1;//记录错误位置的节点值
// cout<<nums.size();
for(int i = 0; i < nums.size()-1; i++) {
if(nums[i] > nums[i+1]) {
y = i + 1;
if(x == -1) {
x = i;
}
}
}
return {nums[x], nums[y]};
}
void recover(TreeNode* root, int count, int x, int y) {
if (root != nullptr) {
if (root->val == x || root->val == y) {
root->val = root->val == x ? y : x;
if (--count == 0) {
return;
}
}
recover(root->left, count, x, y);
recover(root->right, count, x, y);
}
}
void recoverTree(TreeNode* root) {
vector<int> nums;
inorder(root, nums);
pair<int, int> swap = findTwoSwapper(nums);
recover(root, 2, swap.first, swap.second);
}