由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
JobHunting版 - 关于尾递归
相关主题
Flatten Binary Tree to Linked List的recursive解法新鲜出炉的Google电面面经,求祝福
leetcode一题,自己编译没问题,leetcode总是编译出错。请高手看看有人听说过FIS GT.M吗?上面经
一个小题 谁能帮着给点思路 谢谢啦!一道msft的题
到底什么样的二叉树才是平衡二叉树?leetcode交了钱的能share一下题么?
MS a0, a1, ..., b0, b1... 问题F家面经
弱问题,连反转链表都看不懂了Interview question::
G家电面问一个题
非递归求二叉树高度,除了按层次遍历的方法,还可以怎么做?有重复元素的全排列,递归算法
相关话题的讨论汇总
话题: int话题: double话题: array话题: arr话题: ar
进入JobHunting版参与讨论
1 (共1页)
p*****2
发帖数: 21240
1
大家能不能给点例子不能转变成尾递归的?我想写写看。谢谢。
d**e
发帖数: 6098
2
比如 get binary tree height ?

【在 p*****2 的大作中提到】
: 大家能不能给点例子不能转变成尾递归的?我想写写看。谢谢。
y****n
发帖数: 743
3
C(m,n)

【在 p*****2 的大作中提到】
: 大家能不能给点例子不能转变成尾递归的?我想写写看。谢谢。
p*****2
发帖数: 21240
4

m*(m-1)*(m-2)...吗?

【在 y****n 的大作中提到】
: C(m,n)
p*****2
发帖数: 21240
5

这个感觉可以呀。为什么你感觉不行呢?

【在 d**e 的大作中提到】
: 比如 get binary tree height ?
p*****2
发帖数: 21240
6

尾递归
def getHeight(root:TreeNode):Int={
recursion(0,List(root))
}

def recursion(layer:Int, list:List[TreeNode]):Int= list match{
case Nil=> layer
case _ => recursion(layer+1, process(list))
}

def process(list:List[TreeNode]):List[TreeNode]={
var newlist:List[TreeNode]=Nil
for(node<-list){
if(!node.left.isEmpty) newlist=node.left.get::newlist
if(!node.right.isEmpty) newlist=node.right.get::newlist
}
newlist
}

【在 d**e 的大作中提到】
: 比如 get binary tree height ?
d**e
发帖数: 6098
7
我理解得比较肤浅,觉得tail recrusion应该是省空间。
不过你这个bfs是tail recursion,我错了。。

【在 p*****2 的大作中提到】
:
: 尾递归
: def getHeight(root:TreeNode):Int={
: recursion(0,List(root))
: }
:
: def recursion(layer:Int, list:List[TreeNode]):Int= list match{
: case Nil=> layer
: case _ => recursion(layer+1, process(list))
: }

p*****2
发帖数: 21240
8

大牛谦虚了。我也是刚学。看看到底尾递归都能做什么。

【在 d**e 的大作中提到】
: 我理解得比较肤浅,觉得tail recrusion应该是省空间。
: 不过你这个bfs是tail recursion,我错了。。

y****n
发帖数: 743
9
int C(int m, int n)
{
if ((n == 0) || (n == m))
return 1;
else
return C(m - 1, n) + C(m - 1, n - 1);
}

【在 p*****2 的大作中提到】
:
: 大牛谦虚了。我也是刚学。看看到底尾递归都能做什么。

p*****2
发帖数: 21240
10

尾递归
def C(m:Int, n:Int):Int={
recursion(m, 0, None)(n)
}

def recursion(m:Int, i:Int, arr:Option[Array[Int]]):Array[Int]= i match{
case _ if i==m+1 => arr.get
case 0 => recursion(m, 1, Option(Array[Int](0)))
case _ => val ret=process(i,arr.get); recursion(m, i+1, Option(ret))
}

def process(i:Int, arr:Array[Int]):Array[Int]={
val ar=new Array[Int](i+1)
ar(0)=1
ar(i)=1

1 until i foreach(j=>ar(j)=arr(j)+arr(j-1))
ar
}

【在 y****n 的大作中提到】
: int C(int m, int n)
: {
: if ((n == 0) || (n == m))
: return 1;
: else
: return C(m - 1, n) + C(m - 1, n - 1);
: }

相关主题
弱问题,连反转链表都看不懂了新鲜出炉的Google电面面经,求祝福
G家电面有人听说过FIS GT.M吗?上面经
非递归求二叉树高度,除了按层次遍历的方法,还可以怎么做?一道msft的题
进入JobHunting版参与讨论
p*****2
发帖数: 21240
11
今天问了scala group的人了,确实所有的recursion都可以转换成尾递归。这个貌似没
什么悬念了。
y****n
发帖数: 743
12
加一点难度。两个函数相互递归
public static double H(double val, int n)
{
if (n == 0)
return val;
else
{
double left = V(val - 1, n - 1);
double right = V(val + 1, n - 1);
return Math.Sqrt(Math.Abs(left * right));
}
}
public static double V(double val, int n)
{
if (n == 0)
return val;
else
{
double up = H(val * 2, n - 1);
double down = H(val / 2, n - 1);
return Math.Sqrt(Math.Abs(up + down));
}
}
p*****2
发帖数: 21240
13

多谢易山,晚上看看。你是做F#的吗?

【在 y****n 的大作中提到】
: 加一点难度。两个函数相互递归
: public static double H(double val, int n)
: {
: if (n == 0)
: return val;
: else
: {
: double left = V(val - 1, n - 1);
: double right = V(val + 1, n - 1);
: return Math.Sqrt(Math.Abs(left * right));

y****n
发帖数: 743
14
我常用C#

【在 p*****2 的大作中提到】
:
: 多谢易山,晚上看看。你是做F#的吗?

p*****2
发帖数: 21240
15

那怎么对尾递归这么熟?

【在 y****n 的大作中提到】
: 我常用C#
y****n
发帖数: 743
16
我对尾递归不熟,以前与一位朋友讨论面试题,谈到过。
那道题是:两个正整数x和y,求x/y的余数。禁用循环和乘除法。
我只知道有尾递归这个东西,可以避免递归层数过多时压栈溢出。
我从来没想过把普通递归改写成尾递归,所以对这个贴子比较感兴趣。
我也很好奇:
是不是所有的递归都可以写成非递归?
是不是所有的递归都可以写成尾递归?
是不是尾递归都可以改写成循环形式?
前面出的那道题纯属探讨,没有刁难的意思。

【在 p*****2 的大作中提到】
:
: 那怎么对尾递归这么熟?

p*****2
发帖数: 21240
17

我个人感觉应该可以。所以想多练习练习。我也是刚接触这东西。正好一起探讨

【在 y****n 的大作中提到】
: 我对尾递归不熟,以前与一位朋友讨论面试题,谈到过。
: 那道题是:两个正整数x和y,求x/y的余数。禁用循环和乘除法。
: 我只知道有尾递归这个东西,可以避免递归层数过多时压栈溢出。
: 我从来没想过把普通递归改写成尾递归,所以对这个贴子比较感兴趣。
: 我也很好奇:
: 是不是所有的递归都可以写成非递归?
: 是不是所有的递归都可以写成尾递归?
: 是不是尾递归都可以改写成循环形式?
: 前面出的那道题纯属探讨,没有刁难的意思。

p*****2
发帖数: 21240
18

尾递归的实现,不过Scala不支持这种递归的优化。
def H(value:Double, n:Int):Double={
H_helper(Array(value),n)(0)
}

def V(value:Double, n:Int):Double={
V_helper(Array(value),n)(0)
}

def H_helper(arr:Array[Double], n:Int):Array[Double]=n match{
case 0 => caclV(arr)
case _ => {
val ar=new Array[Double](arr.length*2)
for(i<- 0 until arr.length) {
ar(2*i)=arr(i)-1
ar(2*i+1)=arr(i)+1
}
V_helper(ar, n-1)
}
}

def V_helper(arr:Array[Double], n:Int):Array[Double]=n match{
case 0 => caclH(arr)
case _ =>{
val ar=new Array[Double](arr.length*2)
for(i<- 0 until arr.length){
ar(2*i)=arr(i)*2
ar(2*i+1)=arr(i)/2
}
H_helper(ar, n-1)
}
}

def caclH(arr:Array[Double]):Array[Double]={
if(arr.length==1) return arr
val ar=new Array[Double](arr.length/2)
for(i<- 0 until ar.length){
ar(i)=math.sqrt((arr(2*i)*arr(2*i+1)).abs)
}
caclV(ar)
}

def caclV(arr:Array[Double]):Array[Double]={
if(arr.length==1) return arr
val ar=new Array[Double](arr.length/2)
for(i<- 0 until ar.length){
ar(i)=math.sqrt((arr(2*i)+arr(2*i+1)).abs)
}
caclH(ar)
}

【在 y****n 的大作中提到】
: 加一点难度。两个函数相互递归
: public static double H(double val, int n)
: {
: if (n == 0)
: return val;
: else
: {
: double left = V(val - 1, n - 1);
: double right = V(val + 1, n - 1);
: return Math.Sqrt(Math.Abs(left * right));

y****n
发帖数: 743
19
你太牛了!你这是要逼着我学Scala呀!

【在 p*****2 的大作中提到】
:
: 尾递归的实现,不过Scala不支持这种递归的优化。
: def H(value:Double, n:Int):Double={
: H_helper(Array(value),n)(0)
: }
:
: def V(value:Double, n:Int):Double={
: V_helper(Array(value),n)(0)
: }
:

p*****2
发帖数: 21240
20

好呀。一起学习呀。今天准备总结一下尾递归,大牛帮助点评一下。

【在 y****n 的大作中提到】
: 你太牛了!你这是要逼着我学Scala呀!
相关主题
leetcode交了钱的能share一下题么?问一个题
F家面经有重复元素的全排列,递归算法
Interview question::请问走楼梯的问题如何打印所有的路径。
进入JobHunting版参与讨论
y****n
发帖数: 743
21
我试图理解了一下你改写的C(m,n)
有个几问题:
1. 我所理解的尾递归是指在不改变算法的前提下,在函数的结尾处作递归调用。这样
优化编译后,代码可以在进入递归调用之前释放当前函数的堆栈数据。
改编的代码已经修改了算法,计算了很多多余的数据。
比如:C(10,0),原来直接返回1,改编代码会计算C(0,0)-C(10,n)全部数据
2. 原来代码在最深层调用时,对堆栈的占用是O(m)
而改编的代码对内存的占用是O(m^2),这样尾递归的意义就不大了。
3. 感觉上改变后的代码已经不需要递归了,循环貌似更简洁。

【在 p*****2 的大作中提到】
:
: 好呀。一起学习呀。今天准备总结一下尾递归,大牛帮助点评一下。

p*****2
发帖数: 21240
b*****o
发帖数: 715
23
硬币找零问题(100用1,5,10,25有几种表示方法)能不能写成尾递归?
我只能想出用普通递归或者memoization的办法。

【在 p*****2 的大作中提到】
: 总结了一下尾递归
: http://blog.sina.com.cn/s/blog_b9285de20101i5s1.html

p*****2
发帖数: 21240
24

miss掉的大牛的回复。感觉你的理解稍微有点问题。我是这样理解的。
1. 尾递归的本质就是循环
2. 纯FP是没有循环的,所以才需要尾递归。如果有循环的话,确实没必要这么搞。

【在 y****n 的大作中提到】
: 我试图理解了一下你改写的C(m,n)
: 有个几问题:
: 1. 我所理解的尾递归是指在不改变算法的前提下,在函数的结尾处作递归调用。这样
: 优化编译后,代码可以在进入递归调用之前释放当前函数的堆栈数据。
: 改编的代码已经修改了算法,计算了很多多余的数据。
: 比如:C(10,0),原来直接返回1,改编代码会计算C(0,0)-C(10,n)全部数据
: 2. 原来代码在最深层调用时,对堆栈的占用是O(m)
: 而改编的代码对内存的占用是O(m^2),这样尾递归的意义就不大了。
: 3. 感觉上改变后的代码已经不需要递归了,循环貌似更简洁。

p*****2
发帖数: 21240
25

这个应该比yishan那个容易很多。memoization与尾递归并不矛盾吧?

【在 b*****o 的大作中提到】
: 硬币找零问题(100用1,5,10,25有几种表示方法)能不能写成尾递归?
: 我只能想出用普通递归或者memoization的办法。

b*****o
发帖数: 715
26
那可能我对尾递归的理解有误。我的理解是,尾递归的state space不会随着问题规模
的增长而增长。
换句话说,不会因为问题规模的变大而出现overflow。
就以硬币问题为例子,普通递归最终会出现stack overflow。而memoization的table最
终也会overflow。但是,真正的尾递归应该不会出现这种问题。难道不是这样吗?

【在 p*****2 的大作中提到】
:
: 这个应该比yishan那个容易很多。memoization与尾递归并不矛盾吧?

1 (共1页)
进入JobHunting版参与讨论
相关主题
有重复元素的全排列,递归算法MS a0, a1, ..., b0, b1... 问题
请问走楼梯的问题如何打印所有的路径。弱问题,连反转链表都看不懂了
请教一道有趣的算法题,请大侠点拨一下思路G家电面
问一个题目非递归求二叉树高度,除了按层次遍历的方法,还可以怎么做?
Flatten Binary Tree to Linked List的recursive解法新鲜出炉的Google电面面经,求祝福
leetcode一题,自己编译没问题,leetcode总是编译出错。请高手看看有人听说过FIS GT.M吗?上面经
一个小题 谁能帮着给点思路 谢谢啦!一道msft的题
到底什么样的二叉树才是平衡二叉树?leetcode交了钱的能share一下题么?
相关话题的讨论汇总
话题: int话题: double话题: array话题: arr话题: ar