美文网首页
循环与递归对比

循环与递归对比

作者: 快给我饭吃 | 来源:发表于2019-12-01 15:34 被阅读0次

    大学学习递归的时候有一句话印象深刻:所有的递归都可以改写为循环。这句话我是同意的,因为递归其实本质上就是栈的操作。虽然如此,但递归有递归的优点,递归算法写出来的程序都比较简短而且优雅,缺点是其站在了计算机的角度,人很难深究其中,容易陷入递归的汪洋大海中。既然所有的递归都可以改写为循环,反之,那循环是否可以改写为递归呢?

    今天再次想到这个问题,是因为做了《剑指Offer》的一道递归题:合并两个排序的链表,牛客网剑指offer第16道题

    递归和循环相同点

    递归和循环都有退出条件,每次递归或循环执行的程序体都是一样的。while (true)循环和递归最相似,两者思路都很清晰,所以我比较喜欢while (true)循环

    // 递归写法
    public void recursive(int n) {
        // 递归结束条件
        if (n == 0) {
            return;
        }
    
        // 其他子问题,递归解决
        recursive(n - 1);
    }
    
    
    public void theLoop() {
    
        // 循环写法
        while (true) {
            // 循环结束条件
            if (n == 0) {
                break;
            }
    
            // 其他问题继续循环
            n = n - 1;
        }
    }
    

    递归种类

    我大致将递归分为两种:可以有返回值和无返回值,这两个貌似差别挺大,但目前我想不明白。比如这道题,打印从1加到n的和。无返回值的话写起来比较麻烦。

    实现如下:

    /**
     * 自我思考,1加到n无返回值和有返回值两种
     */
    
     public class Sum {
    
        public static void main(String[] args){
            System.out.println(recursiveReturnInt(5));
            recursiveReturnVoid(5, 0);
        }
    
        // 有返回值的递归写法
        public static int recursiveReturnInt(int n){
            if (n == 0) {
                return 0;
            }
            return n + recursiveReturnInt(n - 1);
        }
    
        // 无返回值的递归写法
        public static void recursiveReturnVoid(int n, int sum){
    
            if (n == 0) {
                System.out.println(sum);
                return;
            }
            sum += n;
            recursiveReturnVoid(n - 1, sum);
            
        }
     }
    

    循环是否都可以改为递归

    应该是不可以的,不过解决子问题的循环都可以改为递归。如冒泡排序,反转链表等。冒泡排序n个数时每次都把最大的数排到最后一位,接着排序剩下的n-1位。反转链表每次都反转当前节点和下一个节点,接着指针前进反转下一个节点和下下个节点。

    以下是冒泡排序的非递归和递归写法。

    /**
     * 自我思考,冒泡排序的递归和非递归写法
     */
    
     public class BubbleSortTwoSolution {
    
        public static void main(String[] args) {
    
            int[] array = new int[]{4, 6, 1, 3, 2, 3, 9, 8, 0};
            bubbleSortLoopSolution(array);
            System.out.print("循环写法:");
            for(int i : array) {
                System.out.print(i + " ");
            }
            System.out.println();
    
            array = new int[]{4, 6, 1, 3, 2, 3, 9, 8, 0};
            bubbleSortRecursiveSolution(array, 8);
            System.out.print("递归写法:");
            for(int i : array) {
                System.out.print(i + " ");
            }
            System.out.println();
    
            array = new int[]{4, 6, 1, 3, 2, 3, 9, 8, 0};
            bubbleSortWhileLoopSolution(array);
            System.out.print("while (true)写法:");
            for(int i : array) {
                System.out.print(i + " ");
            }
            System.out.println();
        }
    
        // 冒泡排序循环写法
        public static void bubbleSortLoopSolution(int[] array) {
    
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array.length - i - 1; j++) {
                    if (array[j] > array[j+1]) {
                        int tmp = array[j];
                        array[j] = array[j+1];
                        array[j+1] = tmp;
                    }
                }
            }
        }
    
        // 冒泡排序递归写法
        public static void bubbleSortRecursiveSolution(int[] array, int index) {
    
            if (index < 0) {
                return;
            }
    
            for (int j = 0; j < index; j++) {
                if (array[j] > array[j+1]) {
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
    
            bubbleSortRecursiveSolution(array, index-1);
        }
    
        // while (true)循环写法,跟递归很像
        public static void bubbleSortWhileLoopSolution(int array[]) {
    
            int index = array.length - 1;
            while (true) {
    
                if (index < 0) {
                    break;
                }
    
                for (int j = 0; j < index; j++) {
                    if (array[j] > array[j+1]) {
                        int tmp = array[j];
                        array[j] = array[j+1];
                        array[j+1] = tmp;
                    }
                }
    
                index--;
            }
        }
     }
    

    从上面可以看出来,递归和while(true)循环很像,并且思路很清晰。用递归来解决存在子问题的算法,代码很优雅。

    相关文章

      网友评论

          本文标题:循环与递归对比

          本文链接:https://www.haomeiwen.com/subject/hzizwctx.html