数据结构系列二:递归

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;
}

 

原文地址:https://www.cnblogs.com/oxygenG/p/13458060.html