递归算法
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;
}

浙公网安备 33010602011771号