一些基于归并排序,自下而上的递归题目讲解

首先我们看看归并排序
题目:
在这里插入图片描述

思路:
自底向上
1.MergeSort函数一直二分到只有一个元素,
2.Merge函数代表合并已经两个已经排序的数组(双指针法)
3.回溯过程在MergeSort函数中,回溯也就是自底向上的过程
代码:

class Solution {

private:
    void Merge(vector<int> &arr, int start, int end,int mid, vector<int> &temparr)
    {
        int i_start = start;
        int i_end = mid;
        int j_start = mid + 1;
        int j_end = end;

        int length = 0;
        //合并两个有序序列(为什么就有序了)  思考!!!
        while (i_start<= i_end&& j_start<= j_end)//两个有序数组合并后可能会有个对于的 
        {
            if (arr[i_start]< arr[j_start])
            {
                temparr[length] = arr[i_start];
                length++;
                i_start++;
            }
            else
            {
                temparr[length] = arr[j_start];
                length++;
                j_start++;
            }
        }

        while (i_start<= i_end)//这是判断的
        {
            temparr[length] = arr[i_start];
            length++;
            i_start++;
        }

        while (j_start <= j_end)
        {
            temparr[length] = arr[j_start];
            length++;
            j_start++;
        }

        //辅助空间数据覆盖到原空间
        for (int i=0;i<length;i++)
        {
            arr[start+i]=temparr[i];

        }

    }

    void MergeSort(vector<int> &arr, int start, int end, vector<int> &temparr)
    {

        if (start>=end)
        {
            return;
        }
        //划分到最后是每一个里面只有一个数据 
        int mid = (start + end) / 2;
        MergeSort(arr,start,mid, temparr);
        MergeSort(arr, mid+1, end, temparr);

        Merge(arr, start, end, mid, temparr);
    }
public:
    vector<int> sortArray(vector<int>& nums) 
    {
        int left=0;
        int right=nums.size()-1;
        vector<int> temparr(nums.size(),0);
        MergeSort(nums, left, right,temparr);

        return nums;
    }
};

题目
在这里插入图片描述

思路
这题运用到了归并的思想,代码中
代码:
dfs函数采用自底向上的写法
自底向上特征

maxlen代表最大直径中的结点数 因此最终主函数返回值 是maxlen-1

 int dfs(TreeNode* root)
    {
        if(root==NULL) return 0;

        int leftMax=dfs(root->left);

        int rightMax=dfs(root->right);
		......//函数功能
		.....
		return ..}

函数功能**(返回值)** 代表着当前节点(包含当前节点)以下的最大深度

显然我们应该更新maxlen的时候是(下面的灵魂手绘)
在这里插入图片描述

/**
 * 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 {
private:
    int maxLen=0;

    int dfs(TreeNode* root)
    {
        if(root==NULL) return 0;

        int leftMax=dfs(root->left);

        int rightMax=dfs(root->right);

        maxLen=max(maxLen,leftMax+rightMax+1);

        return max(leftMax,rightMax)+1;//这个是与上层链接的这层节点一下(包含本节点)的最大深度
    }
public:
    int diameterOfBinaryTree(TreeNode* root) {

        if(root==NULL)  return 0;
        

        dfs(root);

        return maxLen-1;

    }
};

题目:
在这里插入图片描述
在这里插入图片描述

思路:
首先dfs函数
1.采用至下而上的方法,也就是一直递归至最终的叶子节点的下一个节点,然后回溯,
2.主要功能是 求当前节点(包含当前节点)以及下面节点的最长的一个和(可能是负数) ,也就是说是一天直线,(没有转弯)。
3.我们更新ret_max的情况就是
在这里插入图片描述

代码:

/**
 * 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 ret_max=INT_MIN;
    int dfs(TreeNode* root)//dfs求当前节点以及下面节点的最长的一个和(可能是负数) ,也就是说是一天直线,(没有转弯)
    {
        if(root==nullptr) return 0;
        int leftMax=max(dfs(root->left),0);//保证是正数,负数的时候,代表下面的节点我们可以舍弃

        int righrMax=max(dfs(root->right),0);//同理

        ret_max=max(ret_max,leftMax+righrMax+root->val);

        return max(leftMax,righrMax)+root->val;

    }
public:
    int maxPathSum(TreeNode* root)
    {
        //if(root==nullptr) return 0;  //题目中强调了二叉树至少有一个节点

        dfs(root);

        return ret_max;
    }
};

题目:
在这里插入图片描述

思路:
由于是搜索数,阴齿自上而下可以解决。

代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        if(root==NULL) return NULL;

        if(root->val>p->val&&root->val>q->val)
        {
            return lowestCommonAncestor(root->left,p,q);
        }
        

        if(root->val<p->val&&root->val<q->val)
        {
            return  lowestCommonAncestor(root->right,p,q);
        }

        return root;
    }
};

题目
在这里插入图片描述

思路:
递归+回溯
自下而上(有局部终止)
1.lowestCommonAncestor找到叶子节点的下一个节点或则p,q节点就返回

2.主要功能是寻找当前节点以及以下节点的是p,q的最近公共祖先
代码

/**
 * 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* leftNode=lowestCommonAncestor(root->left,p,q);

        TreeNode* rightNode=lowestCommonAncestor(root->right,p,q);

        if(leftNode==NULL&&rightNode==NULL) return NULL;

        else if(leftNode==NULL&&rightNode!=NULL) return rightNode;
        else if(leftNode!=NULL&&rightNode==NULL) return leftNode;
        else return root;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值