递归-回溯算法

2023-11-17

一、递归-回溯算法

1.递归的思想

递归就是方法自己调用自己,每次调用的时候传入不同的变量

2.递归的原理

1)每执行一个方法,就在【栈内存】中分配一块空间,该空间是独立的。

2)如果是【基本数据类型】,则每块空间中的变量都是局部变量,是相互【独立】的

3)如果是【引用数据类型】,则每块空间中的变量是【共享】的,因为存的是地址值,new出来的对象都存放在【堆内存】中并分配一个【地址值】,方法执行的时候,会根据栈空间中保存的变量地址值,在堆内存中找到同一个变量,因为地址值指向的都是同一个。

4)每次递归后,条件要【不断收敛】,即必须要保证能退出递归,否则递归就无法结束,会不断在栈内存中分配空间,造成【栈溢出】(StackOverFlow)问题。

二、排列问题

1.排列公式

A_n_m = n*(n-1)*(n-2)*...*(n-m+1)=n!/(n-m)!

2.以A_4_4 = 432*1=4!为例:

1)准备工作

1)创建一个集合prelist:[1,2,3,4]

2)创建一个存储排列结果的集合preList

3)定义一个从preList中遍历取元素,然后添加元素到preList集合中的方法:setNum

2)递归调用setNum方法,在方法内部包括:

1)递归结束的条件:向preList集合中添加4个数,就结束递归,并打印结果

2)判断过程
	【遍历】preList集合,取出preList集合中的第一个元素,如果resList集合中没有该元素,就添加到resList集合;
	否则,继续取出preList集合第二个元素,依次类推,直到元素可以添加到resList集合中。

3)如果经过判断,某个元素添加成功了,则【递归】调用setNum方法,继续添加下一个元素

3)回溯

当成功找到【第一种解法】 [1,2,3,4]时,就【回退】到上一个栈,此时,【栈顶】元素为3,还可以试一下4,所以又将栈顶元素设为4,然后再【递归】设置最后一个数,显然,只能是3。所以,【第二种解法】是[1,2,4,3]。

当找到第二种解法后,在【回退】到上一个栈,因为数字只能设置为3或4,所以没有其他选择了,【继续回退】到上一个栈,当前数字是2,还可以选择3或4,所以先设置为3,然后【递归】设置其他数;在设置为4,递归设置其他数。

到最后,resList集合中【第一个元素为1的排列结果就都找到了】。

然后再将2设置为resList的一个元素,就能将2开头的所有排列结果找到,以此类推,找到以3开头的,以4开头的。

4)最终结果打印的顺序就是上面分析的顺序,即:

[1,2,3,4]
[1,2,4,3]
[1,3,2,4]
[1,3,4,2]

5)注意:回退到上一个栈时,之所以能试一试其他的数,是因为每次递归的时候,都【遍历】了prelist数组。

3.Java代码

public class Permutation {

    static Stack<Integer> stack = new Stack<>();

    public static void main(String[] args) {

        int res = permutation(4, 3);
        System.out.println("A_4_3的结果为:" + res);

        List<Integer> preList = new ArrayList<>();
        preList.add(1);
        preList.add(2);
        preList.add(3);
        preList.add(4);
        System.out.println("preList=" + preList);

        enumerration(preList, 4, 0);
    }

    /**
     * 全排列公式实现
     * @param n 一共有n个
     * @param m 从n中取m个
     * @return 表示一共有多少种取法
     */
    public static int permutation(int n, int m){
        int res = 1;
        /*
            A_4_2 = 4 * 3   循环两次实现:4*1*3
            A_4_3 = 4 * 3 * 2   循环三次实现:4*1*3*2
            A_n_m   需要循环m次实现:n*1*(n-1)*...*(n-m+1)
         */
        for (int i = 0; i < m; i++) {
            res *= n;
            n--;
        }
        return res;
    }

    /**
     * 列举出排列结果
     * 例如A_4_4,排列结果就是在给的四个数中依次不重复地选择一个数
     * @param preList 存放需要排列的数据的列表
     * @param total 表示一共选几次数
     * @param cur 表示当前是第几次选数
     */
    public static void enumerration(List<Integer> preList, int total, int cur){
        if (cur == total){
            System.out.println(stack);
            return;
        }
        for (Integer item : preList) {
            if (!stack.contains(item)){
                stack.push(item);
                enumerration(preList, total, cur+1);
                stack.pop();
            }
        }
    }
}

三、八皇后问题

1.问题描述

任意两个皇后不能处于同一行、同一列或同一斜线上,问有多少种摆法?

跟据稀疏数组的思想,我们把二维数组表示的棋盘压缩成一维数组。
arr[i]=value。i表示第i+1个皇后,value表示这个皇后应该放在第i+1行的第i+1列。

2.思路分析

1)与排列问题类似,先将第一个皇后放在第一行,第一列,然后递归调用放置皇后的方法,直到产生第一个正确解法

2)当产生第一个正确解法后,回退到上一个栈(即倒数第二行),试一下其他的位置,再调用放置皇后的方法,设置最后一行的皇后,依次类推,最终找到了第一个皇后放在第一行第一列的所有正确解

3)然后再将第一个皇后放在第一行第二列,。。。

3.Java代码

在这里插入代码片
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

递归-回溯算法 的相关文章

随机推荐

  • React中的组件以及组件实例的三大属性(详细类的复习)

    前言 我们为什么要模块化 是因为要复用编码 提高效率 react就是面向组件编程 函数式组件 函数不能中作为react的节点 就跟正常写函数一样 需要注意的是首字母需要大写 把函数封装为组件 所以把组件渲染到页面上时要使用组件的形式 因为开
  • Smart Tools 网站的架构之美

    本文将简要介绍Smart Tools工具箱网站的架构设计 带领大家一起领略架构之美 Smart Tools是一款实用的在线工具箱网站 地址 https smart tools cn 总体架构 Smart Tools工具箱网站是采用前后端分离
  • 为什么无法用数组名输出数组的的首地址

    当我们直接输出其他类型数组的数组名时 打印的都是一串地址 而字符数组打印的是字符串 为什么 因为字符串中 0 这个结束符 计算机可以知道在哪里读取结束 所以打印数组名就代表输出里面存储的字符串 其他类型没有结束符 计算机不知道从哪里停止 所
  • vue组件生命周期有哪些?vue2和vue3的生命周期图牢记于心,附面试题1

    单选题 关于vue组件生命周期说法错误的是 A 在data中的对象的某个属性和input双向绑定 修改input的值 在beforeDestroy中获取的值是修改过后的值 B ajax请求可以放在created钩子函数中 C 在create
  • Flutter每次进界面都刷新数据

    前言 需求 每次进去消息中心需要请求接口刷新数据 点击打开子界面返回也要请求数据改变状态 解决方法一 1 在initState方法加载数据 override void initState super initState 加载数据 loadD
  • git基础介绍与GitKraken操作简记

    刚开始尝试使用git的时候 简直是被弄得生不如死啊 写了半天的代码一下子被删了 那时候的心情简直想SHI 后来没办法 抽了点时间学习了一下git的原理 其实就是你的文件现在到底在什么状态 这么一个问题 由于只是了解 所以不知道具体的操作 具
  • Redis有效时间设置及时间过期处理

    本文对redis的过期处理机制做个简单的概述 让大家有个基本的认识 Redis中有个设置时间过期的功能 即对存储在redis数据库中的值可以设置一个过期时间 作为一个缓存数据库 这是非常实用的 如我们一般项目中的token或者一些登录信息
  • 打开PowerPoint提示:PowerPoint上次起送时失败。以安全模式启动PowperPoint将帮助您纠正或发现启动中的问题

    PowerPoint 无法打开 1 问题 PowerPoint 上次启动时失败 以安全模式启动PowerPoint 将帮助您纠正或发现启动中的问题 以便下一次成功启动应用程序 但是在这种模式下 一些功能被禁用 是否使用 安全模式 启动Pow
  • 数学计算模拟类问题:加法,除法和幂,注意越界问题。题 剑指Offer,Pow(x, n) ,Divide Two Integers

    数学计算的模拟类题目 往往是要求实现某种计算 比如两数相除 实现的过程中会有所限定 比如不允许乘法等等 这类题目首先要注意计算过程中本身的特殊情况 比如求相除 则必须首先反映过来除数不能为0 其次要记得考虑负数的情况 如果计算范围不单单是整
  • 简单的matlab分布式计算

    matlab的分布式计算可以理解为一台机器作为client 主控机 其他的机器分别作为计算的结点 要由client进行控制和操作 如果把单机上的 m文件直接放到client运行 是不会产生分布式计算的效果的 只相当于在主控机进行了计算 而其
  • 【JavaScript】defer和async的区别

    转载自 https segmentfault com q 1010000000640869 先来试个一句话解释仨 当浏览器碰到 script 脚本的时候 没有 defer 或 async 浏览器会立即加载并执行指定的脚本 立即 指的是在渲染
  • 华为性格测试通关指南

    一 华为性格测试关键要点 前后一致 积极乐观 吃苦耐劳 二 华为喜欢的人才性格画像 服从领导 能够按部就班按时完成工作 能够死命干活 没有太多性格 比如有野心 好胜 想当领导 坚持己见 坚持自己做事方式 别人有错当面硬刚这些类似的性格 喜欢
  • java实现航班信息查询管理系统

    一 任务概述 二 目录结构 三 详细代码 JDBC工具类模块 package com kaikeba task task010404 utils import com alibaba druid pool DruidDataSource i
  • python打包编译成pyd或者,Python .py生成.pyd文件并打包.exe 的注意事项说明

    最近用python写了一个小程序 想发布出去让人试用又不想暴露源码 搜索了一下发现将py文件编译成pyd文件就能达到目的 转换过程很简单 但是在调用pyd文件并且打包为单个exe文件的时候遇到一个坑 搞了一天才解决 在这里分享一下 首先安装
  • 使用post请求建立长连接实现sse,接收后端主动发来的消息,实现chat-gpt的弹字效果,EventSource的应用

    每日鸡汤 每个你想要学习的瞬间都是未来的你向自己求救 最近在做一个chat相关的功能 然后由于接口返回特别特别慢 所以需要搞一个慢慢等待的效果 就是接口一个单词一个单词的返回 然后前端收到一个展示一个 提升用户体验 说实话我是第一次做这类需
  • 消费者不用手机凭一张脸就能完成支付和转账

    以前出门要看钱包交易完成的节点 而商业活动发生于诸多场景中 商家若想为消费者提供更好的服务 就必须更深入地了解消费人群 赢得消费者的青睐 蜻蜓二代推出的AI刷脸会员功能 帮助商家完成顾客的会员一键开卡 不涉及填表 确认 签字等繁琐的流程 只
  • ETL为什么经常变成ELT甚至LET?

    ETL是将数据从来源端经过清洗 extract 转换 transform 加载 load 至目的端的过程 正常的 ETL 过程应当是 E T L 这三个步骤逐步进行 也就是先清洗转换之后再加载进目标端 通常是数据库 最后在数据库中的只是合理
  • Hive(7) Hive的DML语句-Hive的数据库和表的修改和删除

    Hive 3 DML语句 DML 数据操作语句 导入数据 直接从文件向表中导入数据 load data load data local inpath lt 文件路径 gt overwrite into table lt 表名 gt part
  • 内部类详解

    目录 一 什么是内部类 二 内部类的划分 2 1 实例内部类 2 2 静态内部类 2 3 局部内部类 2 4 匿名内部类 一 什么是内部类 定义 当一个事物的内部 还有一个完整的结构进行描述 而这个内部的完整的结构又只为外部事物提供服务 那
  • 递归-回溯算法

    一 递归 回溯算法 1 递归的思想 递归就是方法自己调用自己 每次调用的时候传入不同的变量 2 递归的原理 1 每执行一个方法 就在 栈内存 中分配一块空间 该空间是独立的 2 如果是 基本数据类型 则每块空间中的变量都是局部变量 是相互