zoukankan      html  css  js  c++  java
  • 数据结构系列二:递归

    1. 原则

    1.1 递归三要素

     1. 明确函数功能,先不管函数里面的代码逻辑是什么,首先要明确自己定义的函数用来干什么

     2. 寻找递归结束条件,递归就是就是函数自己调用自己,不然就是就会出现死循环,最终导致栈溢出StackOveflowError

     3. 寻找函数的等价关系式,不断的缩小参数范围

    1.2 重要规则

     1. 执行一个方法时,就是创建一个新的受保护的独立空间(栈空间)

     2. 方法的局部变量是独立的,不受递归次数的影响

     3. 方法中的引用类型变量是全局共享的,例如数组,hashmap等;

     4. 当一个方法执行完毕的时候(或者return)遵守谁调用就将结果返回给谁

     5. 递归分为递和归两步

    2.  递归示例

    2.1 斐波那契数列

    public class Fibonacci {
    
        public static void main(String[] args) {
            int[] arr = new int[10000];
            System.out.println(fib(10));
            System.out.println(fib2(arr, 10));
        }
    
        /**
         * 求Fibonacci数列前n项和  f(n)=f(n-1)+f(n-2)
         * Fibonacci数列:1,1,2,3,5,8,13..。
         * 1.明确函数功能
         * 2.寻找递归结束条件
         * 3.寻找函数的等价关系式
         *
         * @param n
         * @return
         */
        public static int fib(int n) {
            if (n == 1 || n == 2) {
                return 1;
            }
            return fib(n - 1) + fib(n - 2);
        }
    
        /**
         * 递归优化,避免重复计算
         * @param arr 状态保存
         * @param n
         * @return
         */
        public static int fib2(int[] arr, int n) {
            if (n == 1 || n == 2) {
                return 1;
            }
            //已经计算过,直接返回
            if (arr[n - 1] != 0) {
                return arr[n - 1];
            }
            arr[n - 1] = fib(n - 1) + fib(n - 2);
            return arr[n - 1];
        }
    }
    

    2.2 反转单链表

     例如链表为:1->2->3->4,反转后为 4->3->2->1

     常规思路:遍历链表,treemap存储(key=node,value=next),遍历map,修改key和value顺序,并修改最后一个node的next=null

     第二种思路是:通过递归反转,递归的本质就是找等价关系式,或者是规律,分析如下

     递:
     1>2>3>4
     2>3>4
     3>4
     4
     归:
     4>3
     4>3>2
     4>3>2>1

    public class Digui {
    
        public static void main(String[] args) {
            Node node3 = new Node(4, null);
            Node node2 = new Node(3, node3);
            Node node1 = new Node(2, node2);
            Node head = new Node(1, node1);
    
            System.out.println(reverseList(head));
        }
    
        /**
         * 反转单链表 1->2->3->4
         *
         * @param head
         * @return
         */
        public static Node reverseList(Node head) {
            if (head == null || head.next == null) {
                return head;
            }
            Node newHead = reverseList(head.next);
            Node tmp = head.next;
            tmp.next = head;
            head.next = null;
            return newHead;
        }
    }
    
    @Data
    @AllArgsConstructor
    @ToString
    class Node {
        int data;
        Node next;
    }
    

     

  • 相关阅读:
    Neural Collaborative Filtering 神经网络协同过滤
    pyspark(一) 常用的转换操作
    HO引擎近况20210315
    LeetCode–前 K 个高频元素
    常用十大算法(七)— 克鲁斯卡尔算法
    常用十大算法(六)— 普里姆算法
    LeetCode–数值的整数次方
    LeetCode–二叉树的层次遍历 II
    常用十大算法(五)— 贪心算法
    LeetCode–二进制中1的个数
  • 原文地址:https://www.cnblogs.com/oxygenG/p/13458060.html
Copyright © 2011-2022 走看看