leetcode算法刷题的第十六天
1.leetcode 530.二叉搜索树的最小绝对值
题目链接
这道题首先看到二叉搜索树,所以第一时间会想到中序遍历可以让树里面的节点值序列之后是有序的,这样我们找最小绝对值也就比较方便。
第一种解法:递归法
/*** 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 {
public://中序遍历 左中右vector<int> vec;void traversal(TreeNode* root){if(root==NULL) return;traversal(root->left);vec.push_back(root->val);// 将二叉搜索树转换为有序数组traversal(root->right);}int getMinimumDifference(TreeNode* root) {traversal(root);int result=INT_MAX;if(vec.size()<2) return 0;for(int i=1;i<vec.size();i++){// 统计有序数组的最小差值result=min(result,abs(vec[i]-vec[i-1]));//要加绝对值}return result;}
};
第二种解法:迭代法
/*** 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 {
public://中序遍历 左中右int getMinimumDifference(TreeNode* root) {stack<TreeNode*> st;int result=INT_MAX;TreeNode* current=root;TreeNode* pre=NULL;while(current!=NULL||!st.empty()){if(current!=NULL){// 指针来访问节点,访问到最底层st.push(current);// 将访问的节点放进栈current=current->left;//左}else{current=st.top();//中st.pop();if(pre!=NULL){result=min(result,abs(current->val-pre->val));}pre=current;current=current->right;//右}}return result;}
};
思路总结:遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。同时要学会在递归遍历的过程中如何记录前后两个指针,这也是一个小技巧,学会了还是很受用的。
2.leetcode 501.二叉搜索树中的众数
题目链接
第一种解法:迭代法
/*** 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 {
public://中序遍历 左中右int maxCount=0;//最大次数int count=0;//统计出现的次数TreeNode* pre=NULL;vector<int> result;//放最终结果的结果集void searchBST(TreeNode* current){if(current==NULL) return;searchBST(current->left);//左//中if(pre==NULL){//current指向第一个节点count=1;}else if(pre->val==current->val){//与前一个节点的值相同count++;}else{//与前一个节点不相等count=1;}pre=current;//更新节点if(count==maxCount){result.push_back(current->val);}if(count>maxCount){maxCount=count;//更新最大次数result.clear();// 很关键的一步,不要忘记清空result,之前result里的元素都失效了result.push_back(current->val);}searchBST(current->right);//右return;}vector<int> findMode(TreeNode* root) {count=0;maxCount=0;pre=NULL;//记录的是current的前一个节点result.clear();//这里尽量所有的全局变量都初始化searchBST(root);return result;}
};
第二种解法:迭代法
只要把中序遍历转变成迭代,中间节点的处理逻辑完全一样。
/*** 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 {
public://把中序遍历变成迭代vector<int> findMode(TreeNode* root) {stack<TreeNode*> st;int maxCount=0;int count=0;vector<int> result;TreeNode* current=root;TreeNode* pre=NULL;while(current!=NULL||!st.empty()){if(current!=NULL){// 指针来访问节点,访问到最底层st.push(current);// 将访问的节点放进栈current=current->left;//左}else{current=st.top();//中st.pop();if(pre==NULL){count=1;}else if(pre->val==current->val){count++;}else{count=1;}if(count==maxCount){result.push_back(current->val);}if(count>maxCount){maxCount=count;result.clear();result.push_back(current->val);}pre=current;current=current->right;}}return result;}
};
思路总结:其实这道题本身不难,主要的难点可能就是要想到二叉搜索树的性质,有什么特点,如果能想到这一点,这道题就迎刃而解了,所以,我们看到二叉搜索树的题目的时候,一定要想到中序遍历,这样可能会有一些思路。
3.leetcode 236.二叉树的最近公共祖先
题目链接
如果有一道题我们要处理的顺序是从下往上的话,那么一定是要用到后序遍历,就是左右中。
/*** 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==q||root==p||root==NULL) return root;TreeNode* left=lowestCommonAncestor(root->left,p,q);//左TreeNode* right=lowestCommonAncestor(root->right,p,q);//右if(left!=NULL&&right!=NULL) return root;//中 并且要回溯了if(left!=NULL&&right==NULL) return left;//q p肯定是在左子树中else if(left==NULL&&right!=NULL) return right;//q p肯定是在右子树中else return NULL;//left和right都为空}
};
思路总结:
-
求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从底向上的遍历方式。
-
在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
-
要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。
可以说这里每一步,都是有难度的,都需要对二叉树,递归和回溯有一定的理解。
本题没有给出迭代法,因为迭代法不适合模拟回溯的过程。理解递归的解法就够了。
这道题还是比较难的,主要还是要理解后序遍历和回溯如何使用。