常见的递归

news/2025/1/12 6:03:37/

请添加图片描述

⭐️前言⭐️

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

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

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

🍉博客中涉及源码及博主日常练习代码均已上传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 caseSystem.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.ppmy.cn/news/150767.html

相关文章

npm依赖安装与卸载

安装依赖 【npm install xxx】利用 npm 安装xxx依赖到当前命令行所在目录 【npm install xxx -g】利用npm安装全局依赖xxx 【npm install xxx –save】 安装并写入package.json的dependencies中 【npm install xxx –save-dev】安装并写入package.json的devDependencies中 删…

pyflink给每行加全局流水

[rootmaster pyflink]# cat k103.py from pyflink.datastream import StreamExecutionEnvironment import re import redis # 创建 StreamExecutionEnvironment 对象 env StreamExecutionEnvironment.get_execution_environment() # 读取文件&#xff0c;创建 DataStream 对…

b460m itx/ac Z390I B360pro立式无线网卡接口转sata

b460m itx/ac Z390I B360pro立式无线网卡接口转sata 如b460m itx/ac Z390I B360pro等主板的无线网卡接口都是立式m2 keye接口&#xff0c;而且是在主板的边沿&#xff0c;想要在这接口上扩展sata接口&#xff0c;在空间上有一定的局限。 这里有2种转卡可以解决这类主板转sata出…

常用Q460C.Q460D标准.Q460E和Q460B高强板订货要求

常用Q460C.Q460D标准.Q460E和Q460B高强板订货要求 Q460C.Q460D标准.Q460E和Q460B高强板订货 可看 *用 *户 *名 Q460定义   牌号表示方法   钢的牌号和Q345b&#xff0c;Q690D类似由代bai表屈服强度的汉语拼音字母&#xff0c;屈服强度数值&#xff0c;质量等级符号三个部分…

b460m_itx/ac Z390I B360pro升级无线网卡BCM94360HMB

b460m_itx/ac Z390I B360pro升级无线网卡BCM94360HMB b460m_itx/ac Z390I B360pro主板上都有这个无线网卡的m2接口&#xff0c;常被认为是minipcie接口&#xff0c;在要升级网卡时而买错了网卡。 不得以就用转卡&#xff0c;将主板上的m.2_keyE接口转换成minipcie接口来装将…

b460m itx/ac Z390I B360pro安装苹果网卡BCM963402CS

b460m itx/ac Z390I B360pro安装苹果网卡BCM963402CS b460m_itx/ac Z390I B360pro主板上的这个立式无线网卡的m2/ngff接口&#xff0c; 上次介绍的是如何安装bcm94352hmb网卡。 这次介绍下如何安装苹果网卡BCM963402CS&#xff0c;需要用到的这款转卡。 先掰开转卡成2部分…

b460和z490有什么区别

z490支持超频&#xff0c;并享受更高内存频率 组装电脑选b460还是z490看完你就知道了 http://diannao.jd.com Z490主板定位高端&#xff0c;所以支持超频&#xff0c;意味着最佳适合intel处理器型号后缀带“K”支持超频的CPU&#xff0c;例如i5-10600K、i7-10700K、i9-10900K等…

HC32F460开发之UART+DMA接收不定长数据

文章目录 前言一、过程说明二、代码实现总结 前言 使用hc32平台做产品显示板的开发&#xff0c;主板会通过串口不定时上报设备状态&#xff0c;显示板接收到数据包后&#xff0c;解析并根据主板上报的数据显示设备相应的状态到lcd屏上。关于显示板串口接收这一块&#xff0c;原…