常见的递归

news2024/11/26 8:41:54

请添加图片描述

⭐️前言⭐️

本篇文章分享一些常见的递归题目,为后边的动态规划篇章做铺垫。

🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传GitHub


请添加图片描述

📍内容导读📍

  • 🍅汉诺塔
  • 🍅字符串的全部子序列
  • 🍅字符串的全部子序列(去重)
  • 🍅字符串的全排列
  • 🍅字符串的全排列(去重)
  • 🍅逆序栈

🍅汉诺塔

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

题解思路:
若想把n层汉诺塔从最左边移到最右边,分为以下三大步:
首先把1~n-1层从最左边移到中间,
然后把第n层从最左边移到最右边,
最后再把1~n-1层从中间移到最右边。

移动可以拆分成六个方向,来去嵌套完成递归,如下所示:
代码实现:

public class Hanoi {
    public static void hanoi1(int n) {
        leftToRight(n);
    }

    // 请把1~N层圆盘   从左->右
    public static void leftToRight(int n) {
        if(n==1) {  // base case
            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);
    }

    public 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);
    }

    public 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);
    }

    public 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);
    }

    public 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 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);
    }

    public static void main(String[] args) {
        int n=3;
        hanoi1(3);
    }
}

但其实三个位置,再进一步抽象可以成为from、to和other,实现代码如下:

 public static void hanoi2(int n) {
        if(n>0) {
            func(n,"left","right","mid");
        }
    }

    public static void func(int n,String from,String to,String other) {
        if(n==1) {
            System.out.println("Move 1 from "+from+" to "+to);
        }else {
            func(n-1,from,other,to);
            System.out.println("Move "+n+" from "+from+" to "+to);
            func(n-1,other,to,from);
        }
    }

🍅字符串的全部子序列

题目:
打印一个字符串的全部子序列
题解思路:
字符串的每个位置只需判断要或者不要即可,传递参数path用于存储每个位置的取舍情况,把每种情况记录即为结果。

代码实现:

public class PrintAllSubsequences {
    // s -> "abc" ->
    public static List<String> subs(String s) {
        char[] str=s.toCharArray();
        String path="";
        List<String> ans=new ArrayList<>();
        process(str,0,ans,path);
        return ans;
    }

    // str固定参数
    // str[0...index-1]已经走过了,都在path上
    // str[index...]之后还可以决定
    // 把所有生成的子序列,放入到ans中
    public static void process(char[] str, int index, List<String> ans, String path) {
        if(index== str.length) {
            ans.add(path);
            return;
        }
        // 没有要index位置的字符
        process(str,index+1,ans,path);
        process(str,index+1,ans,path+String.valueOf(str[index]));
    }

    public static void main(String[] args) {
        String test="abc";
        List<String> ans=subs(test);
        for(String s:ans) {
            System.out.println(s);
        }
    }
}

🍅字符串的全部子序列(去重)

题目:
打印一个字符串的全部子序列,要求不要出现重复字面值的子序列
题解思路:
与上题思路相同,只是换为set集合存储path即可完成去重。

代码实现:

public class PrintAllSubsequences {

    public static List<String> subsNoRepeat(String s) {
        char[] str=s.toCharArray();
        String path="";
        HashSet<String> set=new HashSet<>();
        process2(str,0,set,path);
        List<String> ans=new ArrayList<>();
        for(String ss:set) {
            ans.add(ss);
        }
        return ans;
    }

    public 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);
        process2(str,index+1,set,path+String.valueOf(str[index]));
    }

    public static void main(String[] args) {
        String test="accc";
        List<String> ans=subsNoRepeat(test);

        for(String s:ans) {
            System.out.println(s);
        }
    }
}

🍅字符串的全排列

https://leetcode.cn/problems/permutations/
题目:
打印一个字符串的全部排列

代码实现:

class Solution {
    List<List<Integer>> res=new LinkedList<>();
    // 主函数,输入一组不重复的数字,返回他们的全排列。
    public List<List<Integer>> permute(int[] nums) {
    	//记录路径
        LinkedList<Integer> track=new LinkedList<>();
        //路径中的元素会被标记为true,避免重复使用
        boolean[] used=new boolean[nums.length];
        backtrack(nums,track,used);
        return res;
    }
    // 路径记录在track中
    // 选择列表:nums中不存在于track的那些元素
    // 结束条件:nums中的元素全都在track中出现
    void backtrack(int[] nums,LinkedList<Integer> track,boolean[] used) {
    	//触发结束条件
        if(track.size()==nums.length) {
            res.add(new LinkedList(track));
            return;
        }
        for(int i=0;i<nums.length;i++) {
        	// 排除不合法的选择
            if(used[i]) continue;
            // 做选择
            track.add(nums[i]);
            used[i]=true;
            backtrack(nums,track,used);
            // 取消选择
            used[i]=false;
            track.removeLast();
        }
    }
}

🍅字符串的全排列(去重)

https://leetcode.cn/problems/permutations-ii/description/
题目:
打印一个字符串的全部排列,要求不要出现重复的排列

代码实现:

class Solution {
    List<List<Integer>> res=new LinkedList<>();
    // 主函数,输入一组不重复的数字,返回他们的全排列。
    public List<List<Integer>> permute(int[] nums) {
    	//记录路径
        LinkedList<Integer> track=new LinkedList<>();
        //路径中的元素会被标记为true,避免重复使用
        boolean[] used=new boolean[nums.length];
        backtrack(nums,track,used);
        return res;
    }
    // 路径记录在track中
    // 选择列表:nums中不存在于track的那些元素
    // 结束条件:nums中的元素全都在track中出现
    void backtrack(int[] nums,LinkedList<Integer> track,boolean[] used) {
    	//触发结束条件
        if(track.size()==nums.length) {
            res.add(new LinkedList(track));
            return;
        }
        for(int i=0;i<nums.length;i++) {
        	// 排除不合法的选择
            if(used[i]) continue;
            // 做选择
            track.add(nums[i]);
            used[i]=true;
            backtrack(nums,track,used);
            // 取消选择
            used[i]=false;
            track.removeLast();
        }
    }
}

🍅逆序栈

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

public class ReverseStack {
    public static void reverse(Stack<Integer> stack) {
        if(stack.isEmpty()) {
            return;
        }
        int i=f(stack);
        reverse(stack);
        stack.push(i);
    }
    // 栈底元素移除
    // 上面的元素盖下来
    // 返回移除掉的栈底元素
    public static int f(Stack<Integer> stack) {
        int result=stack.pop();
        if(stack.isEmpty()) {
            return result;
        }else {
            int last=f(stack);
            stack.push(result);
            return last;
        }
    }
}

⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

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

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

相关文章

设计模式(三):创建型之原型模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(三)&#xff1a;创建型之原型模式 目录 一、设计模式分类二、原型模式1、概述2、结构2、实现3、扩展&#xff08;深克隆&#xff09; 一、设计…

SSM编程---Day 07

目录 SpringMVC 一、概念 二、springMVC的请求处理流程 三、mvc:annotation-driven 标签的作用 四、HandlerMapping、Handler和HandlerAdapter的介绍 五、SpringMVC 体系结构 六、SpringMVC的常用注解 七、view和controller之间的传值 SpringMVC 一、概念 1、 Spring…

ThreadLocal和局部变量的区别

ThreadLocal为线程提供一个线程级别的储物柜&#xff0c;可以往里面存数据&#xff0c;取数据。数据是专属于线程的。 而局部变量&#xff0c;也是专属于线程的。这样来看&#xff0c;两者似乎功能上是一样的&#xff0c;也确实是一样的。 不过局部变量只能通过显示传参的方式…

C++MFC 面向对象程序设计 小型通讯录管理程序设计

课程名称&#xff1a;面向对象程序设计 实验名称&#xff1a;小型通讯录管理程序设计 1.实验目的 深入理解面向对象技术的封装性、继承性和多态性&#xff0c;掌握面向对象程序设计方法。综合应用C基础知识实现小型应用程序开发。掌握使用C流类库实现数据文件访问的操作方…

LabVIEWCompactRIO 开发指南第七章47 EtherCAT RIO

LabVIEWCompactRIO 开发指南第七章47 EtherCAT RIO 在某些应用中&#xff0c;主I/O和扩展I/O系统需要紧密同步--所有输入和输出必须同时更新。使用确定性总线&#xff0c;主控制器不仅可以知道扩展I/O何时更新&#xff0c;还可以确切地知道数据到达需要多长时间。可以使用NI …

电动葫芦无法运转怎么办?

有关电动葫芦无法起动与运转故障&#xff0c;电动葫芦无法起动怎么办&#xff0c;有没有好的解决办法&#xff0c;检查电源熔丝是否烧断&#xff0c;定子绕组相间短路、接地或断路&#xff0c;以及是否负载过大或传动机械故障等。 电动葫芦无法运转故障怎么办 1、首先&#xf…

vue 3 第二十六章:样式(scoped、深度选择器、全局选择器、css modules、自定义注入名称、css中v-bind)

文章目录 1. 介绍2. 基本使用3. scoped原理4. 深度选择器5. 插槽选择器6. 全局选择器7. 混合使用局部与全局样式8. CSS Modules9. 自定义注入名称10. CSS 中的 v-bind() 1. 介绍 在 Vue 中&#xff0c;我们可以使用 scoped 特性来给组件的样式添加作用域。通过为组件的 <st…

win11 revit2022如何卸载干净

目录结构 杀死相关进程卸载相关应用卸载相关目录删除注册表中的相关数据 注意 &#xff1a;下面的结束任务和删除东西有则删除没有则不用管 杀死相关进程 进入任务管理器&#xff08;control shift esc&#xff09;结束相关任务&#xff08;Autodesk开头的文件和名字中带rev…

交通 | 共乘出行:基于图结构的动态多时空供需网络的均衡度量方法

​ 论文解读 郭王懿&#xff0c;孙楚天&#xff0c;陈泰劼&#xff0c;张云天 ​ 编者按 共乘出行极大地改变了人们的日常出行方式。如何高效运营背后的双边平台是极具挑战性的工作。滴滴出行、Lyft公司是其中的佼佼者。本专题将探讨双边平台运营中的一个关键问题&#xff…

高速吹风筒中的发热丝介绍--【其利天下技术】

高速吹风筒用得发热丝&#xff0c;其实是个大功率的家伙&#xff0c;整个产品它的功耗是最大的。它有什么特别的地方呢&#xff1f;与传统的风筒发热丝&#xff0c;高速风筒发热丝有何要求呢&#xff1f; 一&#xff1a;发热丝工作原理&#xff1a; 发热丝是指由导体材料制成的…

LabVIEWCompactRIO 开发指南第七章46 Ethernet RIO

LabVIEWCompactRIO 开发指南第七章46 Ethernet RIO 使用标准以太网协议扩展I/O时&#xff0c;可以使用NI9148以太网RIO扩展机箱。程序员可以利用现有的网络基础设施&#xff0c;如交换机和路由器。尽管全双工交换机网络消除了数据包冲突&#xff0c;但交换机会引入抖动&#…

LeetCode刷题 --- 哈希表

1. 两数之和 解题思路&#xff1a; 利用哈希表&#xff0c;key存数组当前值&#xff0c;value存数组下标两数之和等于target&#xff0c;可以看做是两个数是配对遍历数组&#xff0c;看哈希表中有没有值和这个当前值配对&#xff0c;如果没有&#xff0c;就存入哈希表如果有&am…

Fiddler抓包工具之fiddler设置过滤

fiddler设置过滤 基本的过滤操作流程以百度为例 步骤&#xff1a; 1、右侧高级工具栏点击Filters》勾选Use Filters》选择Show only Internet Hosts和Show only the following Hosts》在文本框中输入host地址 2、点击Changes not yet saved》再点击Actions》Run Filterset …

【医学图像】图像分割系列.4

介绍几篇使用Transformer结构做医学图像分割的论文&#xff1a;CASTformer&#xff08;NeuralPS2022&#xff09;&#xff0c;PHNet&#xff08;arXiv2023&#xff09;。 Class-Aware Adversarial Transformers for Medical Image Segmentation, NeuralPS2022 解读&#xff1a…

37. C++ 基于范围的for循环、指针空值——nullptr(c++11新特性)

目录 1.基于范围的for循环语法如下&#xff1a; 2.一些编程中的实例 3.指针空值——nullptr c11标准下的NULL和nullptr 今天进行了新的学习&#xff0c;基于范围的for循环。基于范围的 for 循环&#xff08;Range-based for loop&#xff09;是 C11 引入的一种循环结构…

机器学习 监督学习 Week3

Logistic Regression 一个用于分类的算法&#xff0c;模型拟合后&#xff0c;以某些值作为阈值&#xff0c;将数据区分为不同的类别。过去的回归算法中&#xff0c;y的值可以范围很广&#xff0c;而在分类算法中y代表类别&#xff0c;往往只有几个&#xff0c;甚至只有两个(tru…

物联网HMI的关键驱动力—SCADA级功能库和控件库

一、前言 在这个数字化时代&#xff0c;物联网HMI已成为连接人与设备之间的关键纽带&#xff0c;为用户提供直观、智能的交互体验&#xff0c;背后强大的关键驱动力扮演着至关重要的角色&#xff0c;其中SCADA级功能库和控件库的引入成为了物联网HMI设计和开发的核心要素。 S…

论文参考文献怎么引用|Word引用多篇参考文献|word参考文献连续引用|参考文献连续编号|交叉引用

一、参考文献准备 首先将参考文献在段落设置模型中进行编号&#xff0c;通过“交叉引用”对“参考文献”编号引用&#xff0c;以“[x-y]”引用格式实现连续多个文献引用。以实现以[1-3]交叉引用格式来引用[1][2][3] 三个连续参考文献为例说明本方法。 二、参考文献连续编号[…

Redis数据类型之列表List

Redis数据类型之列表List list中的命令如下&#xff1a; lpush&#xff1a;从左边插入&#xff0c;插入的数据是倒叙 LPUSH key value1 [value2] 将一个或多个值插入到列表头部 lpush k1 a b c d e f ; 输出结果 f e d c b a lpop k1; 输出 f 从左边pop弹出时先弹出的是f&…

ESD监控系统、防静电闸机的应用案例

ESD监控系统和防静电闸机是在电子厂、医药厂、半导体厂、航空航天等领域广泛应用的静电措施&#xff0c;可以有效地保护生产线上的产品安全&#xff0c;提高产品质量和可靠性。 近日一家电子元器件公司在其生产线上安装了防静电监控系统、ESD防静电闸机&#xff0c;用于控制人员…