IDC

二叉树:一入递归深似海,从此offer是路人

作者:admin 2021-10-17 我要评论

一看就会,一写就废! 这次我们要好好谈一谈递归,为什么很多同学看递归算法都是一看就会,一写就废。 主要是对递归不成体系,没有方法论,「每次写递归算法 ,都...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

❝一看就会,一写就废!❞

这次我们要好好谈一谈递归,为什么很多同学看递归算法都是“一看就会,一写就废”。

主要是对递归不成体系,没有方法论,「每次写递归算法 ,都是靠玄学来写代码」,代码能不能编过都靠运气。

「本篇将介绍前后中序的递归写法,一些同学可能会感觉很简单,其实不然,我们要通过简单题目把方法论确定下来,有了方法论,后面才能应付复杂的递归。」

这里帮助大家确定下来递归算法的三个要素。「每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法!」

  1. 「确定递归函数的参数和返回值:」确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
  2. 「确定终止条件:」写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
  3. 「确定单层递归的逻辑:」确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

好了,我们确认了递归的三要素,接下来就来练练手:

「以下以前序遍历为例:」

「确定递归函数的参数和返回值」:因为要打印出前序遍历节点的数值,所以参数里需要传入vector在放节点的数值,除了这一点就不需要在处理什么数据了也不需要有返回值,所以递归函数返回类型就是void,代码如下:

  1. void traversal(TreeNode* cur, vector<int>& vec) 

「确定终止条件」:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要要结束了,所以如果当前遍历的这个节点是空,就直接return,代码如下:

  1. if (cur == NULLreturn

「确定单层递归的逻辑」:前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:

  1. vec.push_back(cur->val);    // 中 
  2. traversal(cur->left, vec);  // 左 
  3. traversal(cur->right, vec); // 右 

单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,在看一下完整代码:

前序遍历:

  1. class Solution { 
  2. public
  3.     void traversal(TreeNode* cur, vector<int>& vec) { 
  4.         if (cur == NULLreturn
  5.         vec.push_back(cur->val);    // 中 
  6.         traversal(cur->left, vec);  // 左 
  7.         traversal(cur->right, vec); // 右 
  8.     } 
  9.     vector<int> preorderTraversal(TreeNode* root) { 
  10.         vector<int> result; 
  11.         traversal(root, result); 
  12.         return result; 
  13.     } 
  14. }; 

那么前序遍历写出来之后,中序和后序遍历就不难理解了,代码如下:

中序遍历:

  1. void traversal(TreeNode* cur, vector<int>& vec) { 
  2.        if (cur == NULLreturn
  3.        traversal(cur->left, vec);  // 左 
  4.        vec.push_back(cur->val);    // 中 
  5.        traversal(cur->right, vec); // 右 
  6.    } 

后序遍历:

  1. void traversal(TreeNode* cur, vector<int>& vec) { 
  2.         if (cur == NULLreturn
  3.         traversal(cur->left, vec);  // 左 
  4.         traversal(cur->right, vec); // 右 
  5.         vec.push_back(cur->val);    // 中 
  6.     } 

此时大家可以做一做leetcode上三道题目,分别是:

  • 144.二叉树的前序遍历
  • 145.二叉树的后序遍历
  • 94.二叉树的中序遍历

可能有同学感觉前后中序遍历的递归太简单了,要打迭代法(非递归),别急,我们明天打前中后序的迭代法,打个通透!

本文转载自微信公众号「代码随想录」,可以通过以下二维码关注。转载本文请联系代码随想录公众号。


本文转载自网络,原文链接:https://mp.weixin.qq.com/s/PwVIfxDlT3kRgMASWAMGhA

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 二叉树:一入递归深似海,从此offer是

    二叉树:一入递归深似海,从此offer是

  • 鸿蒙HarmonyOS烧录方法总结

    鸿蒙HarmonyOS烧录方法总结

  • Kubernetes 网络的四种场景分析

    Kubernetes 网络的四种场景分析

  • Java身份证号码识别系统

    Java身份证号码识别系统

腾讯云代理商
海外云服务器