跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 根据一切递归可以转为循环,问个递归中嵌套循环的问题
未分類
18 4 月 2021

根据一切递归可以转为循环,问个递归中嵌套循环的问题

根据一切递归可以转为循环,问个递归中嵌套循环的问题

資深大佬 : punk2sang 5

假如说有代码如下:请问还能将递归改为循环吗
public int add(int n) {
int k = n;
for (int i = 0; i< 3; i++) {
if (n != 1) {
k += add(n – 1);
System.out.println(k);
} else {
k+=0;
System.out.println(k);
}
}
return k;
}
大佬有話說 (18)

  • 資深大佬 : WuSiYu

    递归本质上就是通过函数的栈帧来保存信息,所以通过栈就可以转化任何的递归算法,最经典的比如二叉树的前序、中序、后序遍历都有非递归的写法

  • 資深大佬 : dd112389

    public int add(int n) {
    int k = n;
    for (int i = 0; i< 3; i++) {
    if (n != 1) {
    k += add(n – 1);
    System.out.println(k);
    } else {
    k+=0;
    System.out.println(k);
    }
    }
    return k;
    }

  • 資深大佬 : dd112389

    这是想算累加 ?
    那直接一个循环不就出来了 ?
    var n = 10;
    var sum = 0;
    for (let i = 0; i <= 10; i++) sum += i;

  • 資深大佬 : thedrwu

    自己维护个栈,再 goto 大法

  • 資深大佬 : irytu

    说到这个有点意思的,想问个一样的问题:

    bool reachingPoints(int sx, int sy, int tx, int ty) {
    if (sx == tx && sy == ty) return true;
    int sx1 = sx + sy;
    int sy1 = sy;

    int sx2 = sx;
    int sy2 = sx + sy;

    if ((sx1 > tx || sy1 > ty) && (sx2 > tx || sy2 > ty))
    {
    return false;
    }

    return reachingPoints(sx1, sy1, tx, ty) || reachingPoints(sx2, sy2, tx, ty);
    }

    这个递归怎么变循环?

  • 資深大佬 : GAsss

    如何把任意递归转循环?——编译器编译后看生成的汇编 [狗头]

  • 資深大佬 : abersheeran

    如上所说,编译再反编译即可。哈哈哈哈哈哈

  • 資深大佬 : atuocn

    看看 sicp, 关于递归和迭代的解释。主要的区别是,递归需要使用栈空间,而迭代不需要。大多时候递归算法容易解决,转成迭代算法则不太容易。

  • 資深大佬 : Whurry

    666

  • 資深大佬 : jiangzhizhou

    就不能缩进一下么
    “`Java
    public int add(int n) {
    int k = n;
    for (int i = 0; i< 3; i++) {
    if (n != 1) {
    k += add(n – 1);
    System.out.println(k);
    } else {
    k += 0;
    System.out.println(k);
    }
    }
    return k;
    }
    “`

  • 資深大佬 : jiangzhizhou

    @jiangzhizhou 为啥不支持 MarkDown

  • 資深大佬 : no1xsyzy

    @dd112389 显然不是…… 排除副作用的话
    add :: Int -> Int
    add 1 = 1
    add n = n + 3 * add n
    这是一个指数增长的函数。

    @punk2sang 如果你要保留所有副作用的话就必须自己维护栈帧了。
    不保留副作用的话一方面看下 DP,其实只需要保留 last k
    last = nil
    loop(nn in 1…n){
    k=n
    loop(i in 0..3){
    if(nn != 1){
    k += last
    println(k)
    } else {
    k+=0
    print(k)
    }
    last = k
    }

    虽然上述似乎无法正确地被形式化证明。
    虽然在 nn != 1 前可以添加不变式 nn != 1 => last != nil 但如何保证这个不变式正确似乎比较诡异。

  • 資深大佬 : no1xsyzy

    @no1xsyzy 哦……
    我不应该加上 print 的
    现在这个样子副作用的次数都不对。
    要副作用完全一致还是需要自己维护栈帧。
    ——
    当然还有一种曲线方式
    你可以发现这个副作用也是分治的。
    所以其实可以把副作用构成传参

    add :: (Int, [Char]) -> (Int, [Char])
    add (1, s) = (1, “1n1n1”)
    add (n, s) = (n + 3 * add n, concat $ replicate 3 $ s ++ show k)

    这种简单递归根本不用我说了吧

  • 資深大佬 : misaka19000

    不都是 jmp 吗,有什么不能转的

  • 資深大佬 : yeqizhang

    @irytu 按照前面的人说的编译后反编译,我试了 java 确实反编译出来还是递归。

    public static boolean reachingPoints(int sx, int sy, int tx, int ty) {
    if (sx == tx && sy == ty) {
    return true;
    } else {
    int sx1 = sx + sy;
    int sy2 = sx + sy;
    if ((sx1 > tx || sy > ty) && (sx > tx || sy2 > ty)) {
    return false;
    } else {
    return reachingPoints(sx1, sy, tx, ty) || reachingPoints(sx, sy2, tx, ty);
    }
    }
    }

    不过这代码看起来头疼,结合业务逻辑的目的来看可能还好…

  • 資深大佬 : irytu

    @yeqizhang 哈哈哈 是的 这是之前 leetcode 的一道题的解法

  • 主 資深大佬 : punk2sang

    @GAsss @Whurry @WuSiYu @abersheeran @atuocn @dd112389 @irytu @jiangzhizhou @misaka19000 @no1xsyzy 感谢大家的回复,我后面想了下,这种是不是可以看作就是非递归版的多叉树后序遍历

  • 資深大佬 : no1xsyzy

    @punk2sang 好像确实可以看作对 AST 进行后根遍历

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具