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

名词解释

一.递归

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;
    }
}
相关推荐
风味蘑菇干7 小时前
Stream基础题目
java·算法
KaMeidebaby7 小时前
卡梅德生物技术快报|真核蛋白表达信号肽筛选实验全流程复盘
服务器·前端·数据库·人工智能·算法
霍霍的袁8 小时前
【C++初阶】函数重载详细讲解
开发语言·c++·算法
心中有国也有家8 小时前
CANN 算子开发完全指南——从 TBE DSL 到算子上线全流程
人工智能·经验分享·笔记·分布式·算法
阿文的代码库8 小时前
线段树入门:算法分析
数据结构·算法
水木流年追梦8 小时前
大模型入门-DPO 直接偏好优化
人工智能·学习·算法·机器学习·正则表达式
汉克老师8 小时前
GESP6级C++考试语法知识(二十七、广度优先搜索(二、二维BFS))
c++·算法·图论·宽度优先·广度优先搜索·gesp6级·gesp六级
此生决int8 小时前
算法从入门到精通——位运算
数据结构·c++·算法·蓝桥杯
春栀怡铃声8 小时前
【C++修仙录02】筑基篇:vector 使用
开发语言·c++·算法