算法7.从暴力递归到动态规划0

news2024/11/28 10:39:46

算法|7.从暴力递归到动态规划0

1.汉诺塔

题意:打印n层汉诺塔从最左边移动到最右边的全部过程

解题思路:

  • 把字母抛掉,变成左中右三个盘子
  • 多个盘子能一下到吗?不能,把上边的拿走,最下边的才能放到指位置(leftToRight)
  • 上边的怎么拿,leftToMid。那它具体怎么拿,midToLeft…如此,需要6个子过程
  • 他们之间互相调用,能够满足

核心代码:

public static void hanio(int n){
    leftToRight(n);
}
private static void leftToRight(int n) {
    if(n==1){
        System.out.println("Move 1 from left to right");
        return ;
    }
    leftToMid(n-1);
    System.out.println("Move "+n+" from left to right");
    midToRight(n-1);
}

private static void midToRight(int n) {
    if(n==1){
        System.out.println("Move 1 from mid to right");
        return ;
    }
    midToLeft(n-1);
    System.out.println("Move "+(n)+" from mid to right");
    leftToRight(n-1);
}
private static void leftToMid(int n) {
    if(n==1){
        System.out.println("Move 1 from left to mid");
        return ;
    }
    leftToRight(n-1);
    System.out.println("Move "+(n)+" from left to mid");
    rightToMid(n-1);
}

private static void rightToMid(int n) {
    if(n==1){
        System.out.println("Move 1 from right to mid");
        return ;
    }
    rightToLeft(n-1);
    System.out.println("Move "+(n)+" from right to mid");
    leftToMid(n-1);
}

private static void rightToLeft(int n) {
    if(n==1){
        System.out.println("Move 1 from right to left");
        return ;
    }
    rightToMid(n-1);
    System.out.println("Move "+(n)+" from right to left");
    midToLeft(n-1);
}

private static void midToLeft(int n) {
    if(n==1){
        System.out.println("Move 1 from mid to left");
        return ;
    }
    midToRight(n-1);
    System.out.println("Move "+(n)+" from mid to left");
    rightToLeft(n-1);
}

测试代码

public static void main(String[] args) {
    hanio(3);
}

测试结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xrBorUnz-1685191345292)(F:\typora插图\image-20230527145351725.png)]

2.斐波那契

题意:求斐波那契数列第n项数

**解题思路:**略(之前写过)

核心代码:

private static int fib(int n) {
    if(n==1||n==2){
        return 1;
    }
    return fib(n-1)+fib(n-2);
}

测试代码及测试结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hKNDL3Br-1685191345293)(F:\typora插图\image-20230527145950490.png)]

3.打印全排列(去重+不去重)

题意:1.打印一个字符串的全部排列 2.打印一个字符串的全部排列,要求不要出现重复的排列

解题思路:

  • 当前位置和其他位置交换
  • 清除/恢复现场
  • 当前位置为index~N-1
  • 其他位置index+1到N-1
  • 产生的结果个数为n!个
  • 这里也是,如果字符串为空,也产生结果,不过产生的结果是空串
  • 注意:这里没有再用路径,而是使用的自己,所以加入结果集的时候是String.valueOf(str)
  • 去重的思路有两种:过滤式、剪枝式,过滤即使用去重的集合,这里的剪枝策略则是使用visit数组(因为是字符串,所以大小定为256),判断这个元素在这个位置有没有出现过,若出现过则直接跳下一个

核心代码:

/**
 * 设置更为合适的参数
 *这里老师讲的版本没有再传中间参数,而是自己玩自己,相邻的交换,之后再恢复现场
 * @param test
 * @return
 */
private static List<String> permutation(String test) {
    char[] str=test.toCharArray();
    String path="";
    List<String > list=new ArrayList<>();
    process1(str,0,list);
    return list;
}

private static void process1(char[] str, int index, List<String> list) {
    if(index==str.length){
        list.add(String.valueOf(str));
        return ;
    }
    for (int i = index; i < str.length; i++) {
        swap(str,index,i);
        process1(str,index+1,list);
        swap(str,index,i);
    }
}

private static void swap(char[] str, int a, int b) {
    char tmp=str[a];
    str[a]=str[b];
    str[b]=tmp;
}

/**
 * 剪枝的方式去重,提前终止,效率更高
 * @param test
 * @return
 */
private static List<String> noRepeatpermutation1(String test) {
    char[] str=test.toCharArray();
    String path="";
    List<String > list=new ArrayList<>();
    process2(str,0,list);
    return list;
}

private static void process2(char[] str, int index, List<String> list) {
    if(index==str.length){
        list.add(String.valueOf(str));
        return ;
    }
    boolean[] visit=new boolean[256];
    for (int i = index; i < str.length; i++) {
        if(!visit[str[i]]){
            swap(str,index,i);
            process2(str,index+1,list);
            swap(str,index,i);
            visit[str[i]]=true;
        }
    }
}

/**
 * 过滤方式去重
 * @param test
 * @return
 */
private static HashSet<String> noRepeatpermutation2(String test) {
    char[] str=test.toCharArray();
    String path="";
    HashSet<String> set=new HashSet<>();
    process3(str,0,set);
    return set;
}

private static void process3(char[] str, int index, HashSet<String> set) {
    if(index==str.length){
        set.add(String.valueOf(str));
        return ;
    }
    for (int i = index; i < str.length; i++) {
        swap(str,index,i);
        process3(str,index+1,set);
        swap(str,index,i);
    }
}

测试代码

public static void main(String[] args) {
    String test="acc";
    List<String> ans1=permutation(test);
    List<String> ans2=noRepeatpermutation1(test);
    HashSet<String> ans3=noRepeatpermutation2(test);

    System.out.println("未去重");
    for (String str:ans1) {
        System.out.println(str);
    }
    System.out.println("================");
    System.out.println("剪枝版去重");
    for (String str:ans2) {
        System.out.println(str);
    }
    System.out.println("过滤版去重");
    for(String str:ans3){
        System.out.println(str);
    }
}

测试结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dcRxVADt-1685191345294)(F:\typora插图\image-20230527161900036.png)]

4.打印全部子序列(去重+不去重)

题意:1.打印一个字符串的全部子序列 2.打印一个字符串的全部子序列,要求不要出现重复字面值的子序列

解题思路:

  • 数组为空也产生,结果不过是空集
  • 在数组指针走到头了,收集结果
  • path跟着一块玩

核心代码:

private static List<String> subs(String test) {
    char[] str=test.toCharArray();//空的话也产生,不过是一个空串
    String path="";
    List<String> ans=new ArrayList<>();
    process1(str,0,ans,path);
    return ans;
}
private static void process1(char[] str, int index, List<String> list, String path) {
    if(index==str.length){
        list.add(path);
        return ;
    }
    process1(str,index+1,list,path+str[index]);
    process1(str,index+1,list,path);
}

/**
 * 去重版本
 * @param test
 * @return
 */
private static HashSet<String> subsNoRepeat(String test) {
    char[] str=test.toCharArray();//空的话也产生,不过是一个空串
    String path="";
    HashSet<String> set=new HashSet<>();
    process2(str,0,set,path);
    return set;
}

private static void process2(char[] str, int index, HashSet<String> set, String path) {
    if(index==str.length){
        set.add(path);
        return ;
    }
    process2(str,index+1,set,path+str[index]);
    process2(str,index+1,set,path);

}

测试代码:

public static void main(String[] args) {
    String test="acc";
    List<String> ans1=subs(test);
    HashSet<String> ans2= subsNoRepeat(test);

    for(String str:ans1){
        System.out.println(str);
    }
    System.out.println("===============");
    for(String str:ans2){
        System.out.println(str);
    }
}

测试结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sR4TWrsf-1685191345294)(F:\typora插图\image-20230527151642604.png)]

5.使用递归逆序栈

题意:给定一个栈,请逆序这个栈,不能申请额外的数据结构,只能使用递归函数

解题思路:

  • 栈底的元素不断移除——成为返回值交给系统栈(子过程的栈)
  • 子函数功能:移除栈底元素,上边的元素盖下来,返回移除的 栈顶元素

核心代码:

private static void reverse(Stack<Integer> stack) {
    if(stack.isEmpty()){
        return ;
    }
    int tmp=f(stack);
    reverse(stack);
    stack.push(tmp);
}
//f函数的功能是栈底元素移除掉
//上边的元素盖下来,返回移除的栈顶元素
private static int f(Stack<Integer> stack) {
    int ans=stack.pop();
    if(stack.isEmpty()){
        return ans;
    }else{
        int last=f(stack);
        stack.push(ans);
        return last;
    }
}

测试代码:

public static void main(String[] args) {
    Stack<Integer> stack=new Stack<>();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    stack.push(4);
    stack.push(5);
    reverse(stack);
    while(!stack.isEmpty()){
        System.out.println(stack.pop());
    }
}

测试结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aTAwDm1I-1685191345295)(F:\typora插图\image-20230527162944805.png)]

递归总结

例题总结:

  • 汉诺塔:六个子过程,打印内容为“Move ”+n +“from xx to xxx”

  • 斐波那契:无话可说,1||2||n-1||n-2

  • 打印全部子序列:非去重:str,index,list,path,到头了加入,要与不要;去重:使用HashSet过滤,只是换了一种收集容器

  • 打印全排列:

    总体思路,自己玩自己的(当前位置和可能成为当前位置的元素进行交换n!种可能)先交换,去下个位置,再回复现场(for循环)

    非去重:str,index,list

    去重:剪枝:拜访数组,256,判断当前字符在这个位置出现过没,出现过就要,没出现过就不要;过滤:换了个收集容器HashSet

  • 使用递归逆序栈(不申请额外数据结构):f的功能拿栈底元素:if,ans,else last,push(ans),

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/576871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java汉字转拼音pinyin4j-2.5.0.jar用法

要先下载哦&#xff0c; pinyin4j下载链接 可能会出现Cannot resolve symbol ‘net’&#xff0c;找到上面文件的下载路径&#xff0c;IDEA中File->Project Structure -> Modules->Dependencies import java.util.*; import net.sourceforge.pinyin4j.PinyinHelper;…

算法基础学习笔记——⑬质数\约数

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;算法基础学习 目录 ✨质数 &#x1f353;&#xff08;1&#xff09;质数的判定——试除法 &#x1f353;&#xff08;2&#xff09;分解质因数——试除法 ✨约数 &#x1f353;&#xff08;1&#xff09;试除法求一个数的所…

算法基础学习笔记——⑪拓扑排序\最短路

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;算法基础学习 目录 ✨拓扑排序 &#x1f353;朴素dijkstra算法&#xff1a; &#x1f353;堆优化版dijkstra : &#x1f353;Bellman-Ford算法 &#x1f353;spfa 算法&#xff08;队列优化的Bellman-Ford算法&#xff09; …

操作系统(2.8)--线程的实现

目录 线程的实现方式 1.内核支持线程(KST) 2.用户级线程(ULT) 3.组合方式 线程的实现 1.内核支持线程的实现 2.用户级线程的实现 线程的创建和终止 线程的实现方式 1.内核支持线程(KST) 内核支持线程&#xff0c;与进程相同&#xff0c;是在内核的支持下运行的&#x…

二叉树及其相关题目相关的功能的实现

前言&#xff1a;前面我们简单提及了二叉树的相关初级知识和顺序实现二叉树的相关操作详解&#xff0c;并且由完全二叉树延伸到了堆的相关知识&#xff0c;具体详见二叉树初阶和堆的详解&#xff0c;今天&#xff0c;我们展开二叉树的相关 的链式实现操作和经常考察的二叉树的相…

2023 华为 Datacom-HCIE 真题题库 07--含解析

多项选择题 1.[试题编号&#xff1a;190187] &#xff08;多选题&#xff09;如图所示的拓扑采用了VXLAN分布式网关&#xff0c;SW1上的VBDIF10配置了&#xff1a;arp-proxy local enable命令&#xff0c;则以下描述中正确的有哪些项&#xff1f; A、SW1收到PC1发往PC2的报文&…

【搭建私人图床】使用LightPicture开源搭建图片管理系统并远程访问

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

C#,码海拾贝(22)——“全选主元高斯-约当消去法“求解“线性方程组“的C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> …

天天被开发怼?4个方法区分bug前后端归属,我再也不背锅了!

“开发都这么不友善吗&#xff1f;” 有朋友跟我说&#xff0c;刚上岗经常分不清bug是前端还是后端&#xff0c;一直需要开发帮忙重新指派&#xff0c;甚至还会被开发拿来吐槽.... 其实不是开发态度不好&#xff0c;而是对于前后端分离的应用&#xff0c;既需要进行功能测试&am…

什么是网络安全?如何让普通人简单的了解网络安全

一、介绍网络安全 可以介绍一下河南郑州的网络安全科技馆。网络安全科技馆设置个人安全、政企安全、社会安全、综合竞技四个主展区&#xff0c;帮大家普及网络安全知识。首先&#xff0c;可以从个人安全展区开始游览&#xff0c;了解我们身边的网络安全&#xff0c;原来网络安…

调幅波解调-二极管峰值包络检波器【Multisim】【高频电子线路】

目录 一、实验目的与要求 二、实验仪器 三、实验内容与测试结果 1.观测输入、输出波形&#xff0c;估算检波效率&#xff08;D1接法不同&#xff0c;分别观测&#xff09; 2.观察惰性失真波形(C1100nF&#xff0c;其他参数保持不变) 3.观测负峰切割失真(ma0.8&#xff0c…

【目标检测实验系列】AutoDL线上GPU服务器租用流程以及如何用Pycharm软件远程连接服务器进行模型训练 (以Pycharm远程训练Yolov5项目为例子 超详细)

目录 1. 文章主要内容2. 租用AutoDL服务器详细教程2.1 注册AutoDL账号&#xff0c;并申请学生认证(学生认证有优惠&#xff0c;如果不是学生可以忽略此点)2.2 算力市场选择GPU&#xff0c;并选择初始化配置环境2.3 控制台参数解析&#xff0c;并使用相关参数登录Xftp(Windows与…

Spring Boot如何实现OAuth2授权?

Spring Boot如何实现OAuth2授权&#xff1f; OAuth2是一种授权框架&#xff0c;用于授权第三方应用程序访问受保护的资源。在Web应用程序中&#xff0c;OAuth2通常用于授权用户访问受保护的API。 在本文中&#xff0c;我们将介绍如何使用Spring Boot实现OAuth2授权。我们将使…

5-python的Number类型

内容提要 主要介绍python中的Number类型&#xff1a; python的类型转换&#xff0c;oct()、hex()、bin()函数的使用。 python的整数表示&#xff1a;十进制、二进制、八进制、十六进制。&#xff08;*&#xff0c;0b&#xff0c;0o&#xff0c;0x&#xff09; python中ASCII码…

springboot+java+ssm教材管理系统87k61

教材管理系统&#xff0c;主要的模块包括查看主页、个人中心、教师管理、学生管理、教材分类管理、教材信息管理、个体预订管理、取消预订管理、集体预订管理、集体取消管理、系统管理等功能。系统中管理员主要是为了安全有效地存储和管理各类信息&#xff0c;还可以对系统进行…

开发微信公众号本地调试【内网穿透】

文章目录 前言1. 配置本地服务器2. 内网穿透2.1 下载安装cpolar内网穿透2.2 创建隧道 3. 测试公网访问4. 固定域名4.1 保留一个二级子域名4.2 配置二级子域名 5. 使用固定二级子域名进行微信开发 转载自cpolar内网穿透的文章&#xff1a;微信公众号开发&#xff1a;对接本地开发…

【QT】windows下OpenSSL的使用

设计需求 在QT端实现对字符串的加密与解密 OpenSSL下载教程 本人采用 Win64OpenSSL-1_1_1t.msi&#xff0c;百度网盘下载链接 链接&#xff1a;https://pan.baidu.com/s/1vg4s_1JmCpa68TMc1F2gMw 提取码&#xff1a;u4js OpenSSL安装参考链接 OpenSSL使用的参考链接 OpenSS使用…

onceperrequestfilter 和 webmvcconfigurer 区别

概述 在使用Spring框架进行Web开发的时候,我们经常会遇到需要对每个请求做一些统一的处理的情况。例如,我们可能需要在每个请求到达Controller之前进行身份验证,或者在每个请求结束后记录请求的日志信息。这时候,我们可以使用两种不同的方式来实现这些功能:onceperreques…

一款免费无广、简单易用的安全软件:火绒安全软件

名人说&#xff1a;往者不可谏&#xff0c;来者犹可追。——语出《论语微子篇》 Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; o(‐&#xff3e;▽&#xff3e;‐)o很高兴你打开了这篇博客&#xff0c;跟着步骤一步步尝试安装吧。✧ 目录…

Linux-基础篇:虚拟机环境搭建

目录 1、linux介绍 2、安装vm和centos 2.1、vmware下载 2.2、Centos 下载地址 3、虚拟机三种网络连接方式 3.1、桥接模式 3.2、NAT模式 3.3、主机模式 4、虚拟机克隆 5、虚拟机快照 6、虚拟机迁移和删除 7、安装vmtools 7.1、vmtools作用 7.2、安装vmtools步骤 …