LeetCode530二叉搜索树的最小绝对差
关键点:这道题目不是返回整个数中任意两个节点val的差值。而是比较父节点 左子节点 右子节点 三个数之间的差值。以上的解释有误,其实还是找的全局最小的差值,只不过因为是二叉搜索树,他有前后顺序的。 所以最小的差值一定是相邻的,所以两个指针一个pre 一个cur(就是当前root)比较差值即可。
关于返回值问题,这里使用了一个全局变量 result来记录结果,就不用再在递归里面加返回值了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
TreeNode pre;
int result = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
// 这道题目不是返回整个数中任意两个节点val的差值.
// 而是比较父节点 左子节点 右子节点 三个数之间的差值。
// 以上的解释有误,其实还是找的全局最小的差值,只不过因为是二叉搜索树,他有前后顺序的。
// 所以最小的差值一定是相邻的,所以两个指针一个pre 一个cur(就是当前root)比较差值即可
if(root == null){
return 0;
}
getResult(root);
return result;
}
public void getResult(TreeNode root){
if(root == null){
return;
}
// 左
getResult(root.left);
// 中
if(pre != null){
result = Math.min(result, root.val - pre.val);
}
pre = root; // 叶子结点首先赋值给pre,后面是没计算一次将当前root赋值给pre,root变成下一个
getResult(root.right);
}
}
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
vector<int> nums;
void getNums(TreeNode* node){
if(node == NULL) return;
getNums(node->left);
nums.push_back(node->val);
getNums(node->right);
}
public:
int getMinimumDifference(TreeNode* root) {
getNums(root);
int fast = 1;
int slow = 0;
int ans = INT_MAX;
while(fast<nums.size()){
if(ans > (nums[fast] - nums[slow])){
ans = nums[fast] - nums[slow];
}
fast++;
slow++;
}
return ans;
}
};
双指针的方法,利用中序遍历结合双指针的方法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
int ans = INT_MAX;
TreeNode* pre = NULL;
void getNums(TreeNode* node){
if(node == NULL) return;
getNums(node->left);
if(pre != NULL){
ans = min(ans, node->val - pre->val);
}
pre = node;
getNums(node->right);
}
public:
int getMinimumDifference(TreeNode* root) {
getNums(root);
return ans;
}
};
LeetCode501二叉搜索树中的众数
一开始想用遍历普通二叉树那样,将结果都放到一个map里面,最后得到出现次数最多的数。
思路:结合二叉搜索树的特性,就相当于处理一个数组。只不过不能像处理数组一样,直接从前往后遍历。而是递归,利用双指针比较前后两个元素,同时更新count
,最后比较count
和maxCount
,如果出现了
>
>
>或
=
=
=就要开始更新MAxcount
并记录当前的root.val
.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
TreeNode pre = null;
int count =0;
int MaxCount=0;
ArrayList<Integer> list = new ArrayList<>();
public int[] findMode(TreeNode root) {
find(root);
int[] res = new int[list.size()];
for(int i=0;i<list.size();i++){
res[i] = list.get(i);
}
return res;
}
public void find(TreeNode root){
// 直接在中序遍历的过程中就把结果计算出来
// 可以联想数组的操作
if(root == null){
return;
}
find(root.left);
if(pre == null || pre.val != root.val){ // 这里一定要写成这种情况,不然pre!=null的话在叶子结点的时候回不满足,因为一开始的pre==null的。
count=1;
}
else{
count++;
}
// 处理maxCount
if(count > MaxCount){
list.clear();
list.add(root.val);
MaxCount = count;
}
else if(count==MaxCount){ // 不可以与上面得if结合因为这里的逻辑是当出现两个一样个数的[2, 2, 3, 3]是,直接吧3也添加到list里面。若是,加到上面就是导致2被删除。
list.add(root.val);
}
pre = root;
find(root.right);
}
}
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
vector<int> ans;
int count = 0;
int maxCount = INT_MIN;
TreeNode* pre = NULL;
void traversal(TreeNode* node){
if(node == NULL) return;
traversal(node->left);
if(pre == NULL){
count = 1;
}
else if(pre->val == node->val){
count++;
}
else{
count = 1;
}
pre = node;
if(count > maxCount){
ans.clear();
ans.push_back(node->val);
maxCount = count;
}
else if(count == maxCount){
ans.push_back(node->val);
}
traversal(node->right);
}
public:
vector<int> findMode(TreeNode* root) {
traversal(root);
return ans;
}
};
LeetCode236二叉树的最近公共祖先
模板题
思路:回溯+自底向上+递归+后序遍历(左右中)。
使用回溯,找到了p就返回p,找了了q就返回q。如果找到了他们的父节点就返回这个父节点。后序:因为只有使用后序在可以实现自底向上。不适用迭代是因为迭代不适合模拟回溯(回溯和迭代天生一对)。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p || root ==q){ // 终止条件:如果遇到了空节点返回null
// 如果遇到了p或q 就返回p或q
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q); // 左
TreeNode right = lowestCommonAncestor(root.right, p, q); // 右
if(left == null && right== null){ // 如果左节点或右节点都是null那就向上返回null
return null;
}
else if(left == null && right != null){ // 如果右节点不为空,那就返回right的值,此时可能是p也肯是q 也可能是找到的结果 一直返回到根节点
return right;
}
else if(left != null && right == null){ // 同理
return left;
}
else{ // (left != null && right != null) 这里就是父节点的情况,向上返回父节点。
return root;
}
}
}
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || root == p || root == q){
return root;
}
TreeNode* left = lowestCommonAncestor(root->left, p,q); // 左
TreeNode* right = lowestCommonAncestor(root->right, p, q); // 右
if(left == NULL && right == NULL) return NULL; // 从叶子节点返回的null,如果没有找到q,p 就接着向上返回NULL
else if(left != NULL && right == NULL) return left; // left不为NULL,表示左边找到了一个q或p,但是right为NULL。直接向上返回left
else if(left == NULL && right != NULL) return right; // 同理
else return root; // 这里就是left和right都找到了,因此要返回当前父节点root
}
};