递归,搜索与回溯算法--递归

名词解释

一.递归

1.什么是递归?

函数自己调用自己的情况

2.为什么要用递归?

本质 主问题->相同的子问题 子问题->相同的子问题

3.如何理解递归

1.递归展开的细节图

2.二叉树中的题目

3,宏观看待递归的过程

1.不要在意递归的细节展开图 2,把递归的函数当做一个黑盒(相信他能解决这个问题)

3.相信这个黑盒一定能完成任务

4.如何写好要给递归?

1.先找到一个相同的子问题!!!!->函数头的设计

2.只关心某一个子问题大的实现->函数体的设计

3.注意一下递归函数的出口即可(直到一个问题不能分割)

二.搜索vs深度优先搜索vs深度优先遍历vs宽度优先遍历vs宽度优先搜索vs暴搜

1.深度优先遍历vs深度优先搜索

宽度优先遍历vs宽度优先搜索

遍历是形式 搜索是目的

2.关系图

暴力枚举一遍所有的情况

搜索(暴搜){bfs,dfs}

3.拓展搜索问题

全排列(树状图)

三.回溯与剪枝

回溯的本质就是深搜

回溯就是在深搜的时候发现不通,然后回到上一个选择的过程

剪枝就是把不同的路径剪掉

递归

汉诺塔问题

1.题目描述

在经典汉诺塔问题中,有3根柱子以及N个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子.一开始,所有的盘子自上而下按照升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面) 移动圆盘受到一下限制:1.每次只能移动一个盘子 2.盘子只能从柱子顶端滑出到下一个柱子 3.盘子只能堆在比他大的盘子上

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子上

你需要原地修改栈

例如:

输入:A= 2,1,0 B= \[\] ,C=\[\]

输出: C=2,1,0

2.算法原理

1.如何解决汉诺塔问题:

N=1,A上只有一个盘子,直接把盘子转移到C上

N=2,把A上的第一个盘子放到辅助柱B,再把A上最后一个放到C上,最后把B上的盘子移动到C上

N=3 想要把上面的两个放到B上(N=2) 然后把最后一个放到C上,然后就需要把B上的两个放到C上(N=2)

N=4 思路:先把上面的3个盘子放到B上(N=3) 然后把最后一个盘子放到C上,然后再把B上到3个盘子按照类似的方法放到C上

N=n思路:把n-1个盘子放到辅助柱上

2.为什么可以用递归:

大问题->相同类型的子问题

小问题->相同类型的子问题

3.如何编写递归的问题:

1.重复子问题->函数头 将x柱子上的一堆盘子,借助y柱子,转移到z柱子上 void dfs(x,y,z,n)

2.只关心某一个子问题在做什么?->函数体

dfs(x,y,z,n-1)

x.back()->z

dfs(y,x,z,n-1)

3.递归的出口

n==1 只需要把盘子放到z柱上

3.代码实现

java 复制代码
class Solution {
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        dfs(A,B,C,A.size());
    }

    public void dfs(List<Integer> A,List<Integer> B,List<Integer> C,int n){
        if(n==1){
            C.add(A.remove(A.size()-1));
            return ;
        }
        dfs(A,C,B,n-1);
        C.add(A.remove(A.size()-1));
        dfs(B,A,C,n-1);
    }
}

合并两个有序链表

1.题目描述

将两个升序链表合并为一个新的升序链表并返回,新链表是通过拼接给定的两个链表的所有节点组成的

实例:

输入: l1=1,2,4 l2 = 1,3,4

输出:1,1,2,3,4,4

2.算法原理

解法:递归

关键:找到重复的子问题

1.重复子问题->函数头的设计,合并两个有序链表 Node dfs(l1,l2)

2.只关心某一个问题在做什么事情->函数体的设计 1.先比较大小,选较小的那一个接在节点后面 他接dfs(l1.next,l2)

3.递归的出口,当l1指向空,返回l2,当l2指向空,返回l1

其实这道题也可以用循环来实现

这里我们可以得到以下结论

3.代码实现

java 复制代码
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        return dfs(list1,list2);
    }
    public ListNode dfs(ListNode l1,ListNode l2){
        if(l1==null){
            return l2;
        }
        if(l2==null){
            return l1;
        }
        if(l1.val>=l2.val){
            l2.next = dfs(l1,l2.next);
            return l2;
        }else{
            l1.next = dfs(l1.next,l2);
            return l1;
        }
    }
}

反转链表

1.题目描述

给你单链表的头结点head,请你反转链表,并返回反转后的链表

实例:1->2->3->4->5

返回:5->4->3->2->1

2.算法原理

解法:递归

第一种视角:从宏观角度看待问题

1.让当前节点后面的链表先逆置,返回头结点

2.当前节点添加到逆置后的链表后面即可

第二种视角:将链表看成一颗树(只需要做一次后序遍历即可)

3.代码实现

java 复制代码
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null||head.next==null){
            return head;
        }
        ListNode nH=reverseList(head.next);
        head.next.next=head;
        head.next=null;
        return nH;
    }
}

两两交换链表中的节点

1.题目描述

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头结点,你必须在不修改节点内部的值的情况下完成本题(只能进行节点交换)

输入:1,2,3,4

输出:2,1,4.3

2.算法原理

解法:递归

视角:宏观角度看待递归

3.代码实现

java 复制代码
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head==null||head.next==null){
            return head;
        }
        ListNode nH = swapPairs(head.next.next);
        head.next.next = nH;
        ListNode tmp = head.next;
        head.next = nH;
        tmp.next = head;
        nH = tmp;
        return nH;
    }
}

Pow(x, n)

1.题目描述

实现Pow(x,n) 即计算x的整数n次幂函数

2.算法原理

解法一:暴力循环

解法二:快速幂

实现快速幂:1.递归 2.循环

1.相同子问题->函数头 int pow(x,n)

2.只关心每个子问题做了什么?->函数体

tmp = pow(x,n/2)

return n%2 == 0?tmp*tmp :tmp*tmp*x;

3.递归出口 n = 0 return1

细节问题:1.n有可能是负数 2.n有可能是无穷大

如果n是负数的话,我们直接返回1.0/pow(x,-n)

3.代码实现

java 复制代码
class Solution {
    public double myPow(double x, int n) {
        return n<0?1.0/pow(x,-n):pow(x,n);
    }
    public double pow(double x,int n){
        if(n==0) return 1;
        double tmp=pow(x,n/2);
        return n%2==0?tmp*tmp:tmp*tmp*x;
    }
}
相关推荐
KaMeidebaby9 分钟前
卡梅德生物技术快报|biotin 生物素标记抗体全流程
前端·人工智能·算法·数据挖掘·数据分析
阳明山水15 分钟前
自下而上 vs 自上而下 vs 最优组合预测策略解析
大数据·人工智能·深度学习·算法·机器学习
keykey6.17 分钟前
从逻辑回归到 SVM:不仅仅是“分开“
算法·机器学习·支持向量机
QN1幻化引擎23 分钟前
RingBuffer:用"循环缓冲区"干掉KV Cache的O(n)显存膨胀
算法·github
papership34 分钟前
【入门级-算法-8、图论算法:泛洪算法 (Flood Fill)】
算法·图论
MartinYeung534 分钟前
[论文学习]LLM 情境学习资料的快速精确遗忘技术:基于 In-Context Learning 与量化 K-Means 的 ERASE 方法
学习·算法·kmeans
林森lsjs1 小时前
【日耕一题】5. 青春常数(17届蓝桥杯C++B组第一题)
算法·蓝桥杯
Tisfy1 小时前
LeetCode 3838.带权单词映射:求和、取模、拼接(附python一行版)
python·算法·leetcode·字符串·题解·模拟·取模
め.1 小时前
GJK算法实现细节
算法
AI科技星1 小时前
第六卷:量天尺传奇(几何学)
网络·人工智能·算法·概率论·学习方法·几何学·拓扑学