1、删除的结点无左右子节点,那么直接将其父节点指向NULL;
2、删除的结点只有1个子节点,分左右两种情况,直接将其父节点指向删除节点的子节点;
3、删除节点有2个子节点,这是最麻烦的情况了,最好是画个图理解,具体而言:
TreeNode* deleteNode(TreeNode* root, int key) {
if(root==NULL) return NULL;
if(root->val==key){
//情况一和情况二
if(root->left==NULL) return root->right;
if(root->right==NULL) return root->left;
//情况三:此时需要找到最近的一个大于当前结点值的元素
TreeNode* RminNode=FindMin(root->right);
root->val=RminNode->val;
root->right=deleteNode(root->right,RminNode->val);
}
else if(key<root->val){
root->left=deleteNode(root->left,key);
}
else if(key>root->val){
root->right=deleteNode(root->right,key);
}
return root;
}
TreeNode* FindMin(TreeNode* root){
if(root->left) return FindMin(root->left);
else return root;
}
};
利用中序求出有序的序列,然后基于这个序列来找
int Max_time=0,Max_number,n=0;
vector<int> v;
map<int,int> m;
vector<int> findMode(TreeNode* root) {
InOrder(root);
map<int,int>::iterator it;
for(it=m.begin();it!=m.end();it++){
if(it->second>Max_time){
Max_time=it->second;
Max_number=it->first;
}
}
for(it=m.begin();it!=m.end();it++){
if(it->second==Max_time){
v.push_back(it->first);
}
}
return v;
}
void InOrder(TreeNode* root){
if(root==NULL) return ;
InOrder(root->left);
if(m.find(root->val)!=m.end()) m[root->val]++;//已经存在map中了
else m.insert(pair<int,int>(root->val,1));
InOrder(root->right);
}
利用先序遍历,注意下按照递归的思想去加括号,注意只有右子树存在也要加两对括号
string ans="";
string tree2str(TreeNode* t) {
PreOrder(t);
return ans;
}
void PreOrder(TreeNode* root){//pos代表当前根结点的位置
if(root==NULL) return;
ostringstream os;
os<<root->val;
ans+=os.str();
if(root->right){//右子树存在,则左右都要有括号
ans+='(';
PreOrder(root->left);
ans+=')';
ans+='(';
PreOrder(root->right);
ans+=')';
}
else if(root->left){//只有左子树存在,右子树的括号不用写
ans+='(';
PreOrder(root->left);
ans+=')';
}
}
int ans=0;
int findTilt(TreeNode* root) {
SumTree(root);
return ans;
}
int SumTree(TreeNode* root){
if(root==NULL) return 0;
int lsum=SumTree(root->left);
int rsum=SumTree(root->right);
ans+=abs(lsum-rsum);
return root->val+lsum+rsum;
}
用双指针(left,right)+递归实现,注意传参的类型!!
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return solve(nums.begin(),nums.end());
}
TreeNode* solve(vector<int>::iterator left, vector<int>::iterator right){
if(left == right) return NULL;
auto it = max_element(left,right);
TreeNode* node = new TreeNode(*it);
node->left = solve(left,it);
node->right = solve(it+1,right);
return node;
}
这里递归就是先拆分,得到最底层的值后再合并,
拆分就是分成左右子树,最终就是start>end 返回{NULL}。
合并的时候要用两个for循环来实现不同的排列。。。
注:若只是求种数,可以用卡塔兰数计算
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> res;
if(n==0) return res;
return generateTreesCore(1, n);
}
vector<TreeNode*> generateTreesCore(int start, int end){
vector<TreeNode*> res;
if(start>end){
return {NULL};
}
else{
for(int i = start;i<=end;++i){//表示以i为节点构建树
vector<TreeNode*> left = generateTreesCore(start, i-1);//构建左子树
vector<TreeNode*> right = generateTreesCore(i+1, end);//构建右子树
//此时左右子树都有值.要把他们合并在一起。
for(auto r: right){
for(auto l: left){
TreeNode* temp = new TreeNode(i);//把每个节点构建出来。
temp->left = l;
temp->right = r;
res.push_back(temp);
}
}
}
}
return res;
}
vector<int> order;
void recoverTree(TreeNode* root) {
InOrder(root);
//先得到正确的序列
sort(order.begin(),order.end());
recover(root,order);
}
void InOrder(TreeNode* root){
if(root==NULL) return ;
InOrder(root->left);
order.push_back(root->val);
InOrder(root->right);
}
void recover(TreeNode* root,vector<int>& rec){
if(root ==NULL){
return;
}
recover(root->left,rec);
//
if(root->val == rec[0]){
rec.erase(rec.begin());
}else{
//若不同则修改为相同
root->val = rec[0];
rec.erase(rec.begin());
};
recover(root->right,rec);
}
//q1记录正序,q2记录反序
queue<TreeNode*> q1;
queue<TreeNode*> q2;
vector<vector<int>> ans;
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
if(root==NULL) return ans;
q1.push(root);
q2.push(root);
TreeNode* pre_last1=root;
TreeNode* last1=root;
TreeNode* pre_last2=root;
TreeNode* last2=root;
int level=0;
vector<int> temp;
while(!q1.empty()&&!q2.empty()){
TreeNode* p1=q1.front();
q1.pop();
TreeNode* p2=q2.front();
q2.pop();
if(p1->left){
last1=p1->left;
q1.push(p1->left);
}
if(p1->right){
last1=p1->right;
q1.push(p1->right);
}
if(p2->right){
last2=p2->right;
q2.push(p2->right);
}
if(p2->left){
last2=p2->left;
q2.push(p2->left);
}
if(level==0) temp.push_back(p1->val);
else temp.push_back(p2->val);
//两个同时到达当前行的最后一个
if(p1==pre_last1){
pre_last1=last1;
pre_last2=last2;
if(level==0){
ans.push_back(temp);
temp.clear();
level=1;
}
else{
ans.push_back(temp);
temp.clear();
level=1-level;
}
}
}
return ans;
}
int target;
bool flag=false;
vector<vector<int>> ans;
vector<vector<int>> pathSum(TreeNode* root, int sum) {
if(root==NULL) return ans;
target=sum;
vector<int> temp;
temp.push_back(root->val);
dfs(root,0,temp);
return ans;
}
void dfs(TreeNode* root,int sum,vector<int>& temp){
int cur_sum=sum+root->val;
//cout<
if(root->left==NULL&&root->right==NULL){
if(sum+root->val==target){
ans.push_back(temp);
flag=true;
return ;
}
}
if(root->left){
temp.push_back(root->left->val);
dfs(root->left,cur_sum,temp);
temp.pop_back();
}
if(root->right){
temp.push_back(root->right->val);
dfs(root->right,cur_sum,temp);
temp.pop_back();
}
}
public:
int maxh;
int maxPathSum(TreeNode* root) {
//if(root==NULL) return 0;
maxh=root->val;
max_path(root);
return maxh;
}
int max_path(TreeNode* root){
if(root==NULL) return 0;
int cur=root->val;
int l=max_path(root->left)+cur;
int r=max_path(root->right)+cur;
//cout<<"root"<val<
//cout<<"left:"<
if(l>maxh) maxh=l;
if(r>maxh) maxh=r;
if(l+r-cur>maxh) maxh=l+r-cur;
//加上这个是因为有的防止每次计算最大路径都必须包括叶结点(对于已经小于0的分支可以直接抛弃)
if(l<0&&r<0) return 0;
else return max(l,r);
}
/*
两个节点p,q分为两种情况:
p和q在相同子树中
p和q在不同子树中
从根节点遍历,递归向左右子树查询节点信息
递归终止条件:如果当前节点为空或等于p或q,则返回当前节点
递归遍历左右子树,如果左右子树查到节点都不为空,则表明p和q分别在左右子树中,因此,当前节点即为最近公共祖先;
如果左右子树其中一个不为空,则返回非空节点。
*/
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&&right) return root;
if(left==NULL) return right;
else return left;
}