今天分享LeetCode第99题:恢复二叉搜索树
前言
本文将用图文结合的方式来较详细的阐述LeetCode第99题的解题过程和思路。
本人才疏学浅,如有错误请多担待并联系本人,感谢各位给本人一个学习的机会。
一、题目描述
给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
示例:
二、思想和方法详述
1.解题思想
解题之前先谈何为二叉搜索树,简单地说,二叉搜索树就是根节点的所有左子树的节点值都比根节点小,所有右子树的节点值都比根节点大。
根据题目描述和示例,我们发现只需要找到节点中有误的两个结点,并将其交换即可。但是怎么找到这两个有误的结点是重中之重,观察发现,二叉搜索树的中序遍历结果呈递增式,故可对题目中的所给的二叉树进行中序遍历,利用中序遍历的结果来找出违背中序遍历的两个节点值并在原二叉树中对两个值进行交换,即可得到本题答案。
2.解题步骤详述
接下来我们对本题的详细解答步骤运用图示进行详细的阐述:
- 搜索二叉树的中序遍历
根据上图可以看出搜索二叉树的中序遍历结果是呈递增式的,接下来我们将利用这个特性进行寻找违背此特性的两个节点。
- 对题目所给的二叉树进行中序遍历
我们以题目示例为例:
由该二叉树的中序遍历结果可以看出,此结果并非呈递增式,我们观察发现,结果中的节点 “ 3 ”与节点“ 2 ”有误,需要调换位置。
调换之后的二叉树和中序遍历的结果为:
- 选取违规值的取值标准
第一个节点:是第一个按照中序遍历时候前一个节点大于后一个节点,我们选取前一个节点。
第二个节点:是在第一个节点找到之后,后面出现前一个节点大于后一个节点,我们选择后一个节点。
三、代码实现
Python代码:
class Solution:
def recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
firstNode = None
secondNode = None
pre = TreeNode(float("-inf"))
stack = []
p = root
while p or stack:
while p:
stack.append(p)
p = p.left
p = stack.pop()
if not firstNode and pre.val > p.val:
firstNode = pre
if firstNode and pre.val > p.val:
#print(firstNode.val,pre.val, p.val)
secondNode = p
pre = p
p = p.right
firstNode.val, secondNode.val = secondNode.val, firstNode.val
C++代码:
class Solution {
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> findTwoSwapped(vector<int>& nums) {
int n = nums.size();
int index1 = -1, index2 = -1;
for (int i = 0; i < n - 1; ++i) {
if (nums[i + 1] < nums[i]) {
index2 = i + 1;
if (index1 == -1) {
index1 = i;
} else {
break;
}
}
}
int x = nums[index1], y = nums[index2];
return {x, y};
}
void recover(TreeNode* r, int count, int x, int y) {
if (r != nullptr) {
if (r->val == x || r->val == y) {
r->val = r->val == x ? y : x;
if (--count == 0) {
return;
}
}
recover(r->left, count, x, y);
recover(r->right, count, x, y);
}
}
void recoverTree(TreeNode* root) {
vector<int> nums;
inorder(root, nums);
pair<int,int> swapped= findTwoSwapped(nums);
recover(root, 2, swapped.first, swapped.second);
}
};
Java代码:取自本文
class Solution {
public void recoverTree(TreeNode root) {
List<Integer> nums = new ArrayList<Integer>();
inorder(root, nums);
int[] swapped = findTwoSwapped(nums);
recover(root, 2, swapped[0], swapped[1]);
}
public void inorder(TreeNode root, List<Integer> nums) {
if (root == null) {
return;
}
inorder(root.left, nums);
nums.add(root.val);
inorder(root.right, nums);
}
public int[] findTwoSwapped(List<Integer> nums) {
int n = nums.size();
int index1 = -1, index2 = -1;
for (int i = 0; i < n - 1; ++i) {
if (nums.get(i + 1) < nums.get(i)) {
index2 = i + 1;
if (index1 == -1) {
index1 = i;
} else {
break;
}
}
}
int x = nums.get(index1), y = nums.get(index2);
return new int[]{x, y};
}
public void recover(TreeNode root, int count, int x, int y) {
if (root != null) {
if (root.val == x || root.val == y) {
root.val = root.val == x ? y : x;
if (--count == 0) {
return;
}
}
recover(root.right, count, x, y);
recover(root.left, count, x, y);
}
}
}
C语言代码:取自本文
int len, max_size;
void inorder(struct TreeNode* root, int** nums) {
if (root == NULL) {
return;
}
inorder(root->left, nums);
(*nums)[len++] = root->val;
if (len == max_size) {
max_size <<= 1;
(*nums) = (int*)realloc((*nums), sizeof(int) * max_size);
}
inorder(root->right, nums);
}
int* findTwoSwapped(int* nums) {
int index1 = -1, index2 = -1;
for (int i = 0; i < len - 1; ++i) {
if (nums[i + 1] < nums[i]) {
index2 = i + 1;
if (index1 == -1) {
index1 = i;
} else {
break;
}
}
}
int x = nums[index1], y = nums[index2];
int* ret = (int*)malloc(sizeof(int) * 2);
ret[0] = x, ret[1] = y;
return ret;
}
void recover(struct TreeNode* r, int count, int x, int y) {
if (r != NULL) {
if (r->val == x || r->val == y) {
r->val = r->val == x ? y : x;
if (--count == 0) {
return;
}
}
recover(r->left, count, x, y);
recover(r->right, count, x, y);
}
}
void recoverTree(struct TreeNode* root) {
len = 0, max_size = 1;
int* nums = (int*)malloc(sizeof(int));
inorder(root, &nums);
int* swapped = findTwoSwapped(nums);
recover(root, 2, swapped[0], swapped[1]);
}
总结
生命不息,刷题不止。今天的分享就到这里,若有错误,请联系本人进行更改。最后,感谢我家莫莫的耐心陪伴和等候。