查看: 4362| 回复: 16
跳转到指定楼层
上一主题 下一主题
收起左侧

[其他] 求助前辈 recursion怎么想

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
请位前辈们
recursion怎么才能进步
感觉自己遇到recursion就没有思路。
前辈们都是怎么想recursion的 有什么推荐学习的东西吗。

上一篇:请教一下,买Leetcode premium 买国内站还是美国站?
下一篇:想学编程,做一个可可爱爱的女程序员
推荐
twtypsj 2021-3-18 02:42:06 | 只看该作者
全局:
本帖最后由 twtypsj 于 2021-3-18 02:46 编辑

个人认为递归函数首先要考虑的是什么情况下需要退出递归,当知道了什么情况下需要退出递归之后,再考虑在当前递归层需要做哪些事情。
整体的思路是把整个过程想象成一个大树,每个节点代表一个状态,从第一层往下层迁移的时候考虑什么状态需要修改,在从下层回到上层的时候,什么状态需要恢复。

还有就是哪些状态可以保存下来,这样可以剪枝来优化时间。

用琪琪题举例的话,

  1. class Solution {
  2. public:
  3.     void dfs(int n, int k, int start, vector<int>& path, vector<vector<int>>& res)
  4.     {
  5.         if(start > n)
  6.         {
  7.             if(path.size()==k) res.push_back(path);
  8.             return;
  9.         }
  10.         path.push_back(start);
  11.         dfs(n,k, start+1, path, res);
  12.         path.pop_back();
  13.         dfs(n,k, start+1, path, res);
  14.     }
  15.     vector<vector<int>> combine(int n, int k) {
  16.         
  17.         vector<vector<int>> res;
  18.         vector<int> path;
  19.         dfs(n,k,1,path,res);
  20.         return res;
  21.     }
  22. };
复制代码


递归函数dfs,首先考虑什么情况下需要退出递归,这种情况下,start大于n的时候说明所有的数已经访问过了,所以需要退出。
第二步要考虑的是在当前递归层里要做什么,这里需要做两件事,一件事是如果把start的值考虑在这个组合中,剩下的由递归解决,第二件事是如果不把start的值考虑在这个组合中结果是什么。所以这种情况下,path需要先保存好start,做完要做的事情,然后恢复path的状态,也就是pop_back。


浅显的理解,不知道是否能帮到你。顺便求大米 :P

评分

参与人数 5大米 +10 收起 理由
不知道小帅 + 1 赞一个
blackrose + 1 赞一个
CY皮皮鱼 + 1 赞一个
sophiaf0409 + 2 很有用的信息!
14417335 + 5

查看全部评分

回复

使用道具 举报

推荐
1m3fdstring 2021-3-23 00:50:34 | 只看该作者
全局:
递归分三步走
1,先想好退出条件,比如为空时返回什么值,index超出时返回什么值
2,内部调用一下本函数,比如LinkedList就用LinkedList.next调用自身函数,tree就是tree.left和tree.right调用函数
3,最后返回函数一开始定义的值。

评分

参与人数 1大米 +1 收起 理由
海绵宝宝 + 1 赞一个

查看全部评分

回复

使用道具 举报

全局:
不清楚楼主背景很难准确推荐,不过如果是以学习为目的,可以尝试下学习 The little schemer 这本书。如前言所说 “The goal of this book is to teach the reader to think recursively.”

有什么后续问题,欢迎提问。

最后,求加米。

评分

参与人数 1大米 +1 收起 理由
YQD + 1 赞一个

查看全部评分

回复

使用道具 举报

🔗
wisdompeak2 2021-3-17 11:01:56 | 只看该作者
全局:
想法设法把大问题分解为若干个相同的小问题,这些小问题都是同样的解法,只是数据不同。
多刷树的题目。树这个数据结构是递归定义的,因此90%的树的算法也都是递归来解的。刷熟了就对递归有感觉了。

评分

参与人数 2大米 +3 收起 理由
14417335 + 2
不知道小帅 + 1 赞一个

查看全部评分

回复

使用道具 举报

🔗
 楼主| sukiyy 2021-3-17 12:23:46 来自APP | 只看该作者
全局:
wisdompeak2 发表于 2021-03-16 20:01:56
想法设法把大问题分解为若干个相同的小问题,这些小问题都是同样的解法,只是数据不同。
多刷树的题目。树这个数据结构是递归定义的,因此90%的树的算法也都是递归来解的。刷熟了就对递归有感觉了。
我也知道是拆解 可是怎么拆是问题
请问需要考虑call stack吗 还是宏观的思考呢。
哎 自己好难。
回复

使用道具 举报

🔗
wisdompeak2 2021-3-17 15:16:22 | 只看该作者
全局:
sukiyy 发表于 2021-3-17 12:23
我也知道是拆解 可是怎么拆是问题
请问需要考虑call stack吗 还是宏观的思考呢。
哎 自己好难。

递归是一种高屋建瓴的哲学思想。具体怎么拆那样看具体问题了。
大多数问题本身就是可以递归解决的,举个简单的例子:求一棵树所有元素的val的和,等于根节点的val+左子树所有元素的val的和+右子树所有元素的val的和,后两者就是递归调用。要把这种思想提升到一种哲学高度去体会。
另外部分稍微难一点的题,可能要设计一个稍微不同的递归问题。比如求一棵树里的最长直径。任何一条直径都有一个拐点,直径的长度就是拐点往左走到叶子的最远距离+拐点往右走到叶子的最远距离。所以此时的递归问题就是:求一个节点到叶子节点的最远距离。
回复

使用道具 举报

🔗
 楼主| sukiyy 2021-3-18 22:14:43 来自APP | 只看该作者
全局:
twtypsj 发表于 2021-03-17 11:42:06
个人认为递归函数首先要考虑的是什么情况下需要退出递归,当知道了什么情况下需要退出递归之后,再考虑在当前递归层需要做哪些事情。
整体的思路是把整个过程想象成一个大树,每个节点代表一个状态,从第一层往下
谢谢🙏我觉得你说的这个哲学思想很有帮助 我总是想要往里面死绕。
回复

使用道具 举报

全局:
递归就三步:
1. 如何停止
2. 如何进行下一步
3.初始状态是什么

比如 斐波那契数列

1. 如何停止 - if (n ==1 || n==2) then return 1.
2. 如何下一步 fnc(n-2) + fnc(n-1)
3. 初始状态 - fnc(初始值)

如果需要backtracking 那再加一步
4. 如何step back.

稳稳地
回复

使用道具 举报

🔗
tiancaihb 2021-3-18 23:56:20 | 只看该作者
全局:
把你要求的内容用函数表示出来,例如cost=f(x,y)。然后看f(x,y)怎么用f(x',y')表达。最后找能求出来的边界值。
回复

使用道具 举报

🔗
kamia 2021-3-19 01:10:34 | 只看该作者
全局:
sukiyy 发表于 2021-3-16 20:23
我也知道是拆解 可是怎么拆是问题
请问需要考虑call stack吗 还是宏观的思考呢。
哎 自己好难。

不用考虑call stack,就假设递归函数已经是一个第三方实现好的函数,然后用在自己的函数里面。只不过自己的函数正好和这个“第三方函数”同名。
回复

使用道具 举报

🔗
hjldtc 2021-3-19 01:41:59 来自APP | 只看该作者
全局:
多写写dfs tree traversal还有dp top down的题目就可以了 这个recursion需要你灵活用的 刷题刷多了就有感觉了 先多看看答案 刷题刷多了 你自己的思维方式也会像答案的大神一样
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表