class038 经典递归解析【算法】

news2024/11/24 19:49:38

class038 经典递归解析

算法讲解038【必备】常见经典递归过程解析

在这里插入图片描述

code1 字符串的全部子序列

// 字符串的全部子序列
// 子序列本身是可以有重复的,只是这个题目要求去重
// 测试链接 : https://www.nowcoder.com/practice/92e6247998294f2c933906fdedbc6e6a

package class038;

import java.util.HashSet;

// 字符串的全部子序列
// 子序列本身是可以有重复的,只是这个题目要求去重
// 测试链接 : https://www.nowcoder.com/practice/92e6247998294f2c933906fdedbc6e6a
public class Code01_Subsequences {

	public static String[] generatePermutation1(String str) {
		char[] s = str.toCharArray();
		HashSet<String> set = new HashSet<>();
		f1(s, 0, new StringBuilder(), set);
		int m = set.size();
		String[] ans = new String[m];
		int i = 0;
		for (String cur : set) {
			ans[i++] = cur;
		}
		return ans;
	}

	// s[i...],之前决定的路径path,set收集结果时去重
	public static void f1(char[] s, int i, StringBuilder path, HashSet<String> set) {
		if (i == s.length) {
			set.add(path.toString());
		} else {
			path.append(s[i]); // 加到路径中去
			f1(s, i + 1, path, set);
			path.deleteCharAt(path.length() - 1); // 从路径中移除
			f1(s, i + 1, path, set);
		}
	}

	public static String[] generatePermutation2(String str) {
		char[] s = str.toCharArray();
		HashSet<String> set = new HashSet<>();
		f2(s, 0, new char[s.length], 0, set);
		int m = set.size();
		String[] ans = new String[m];
		int i = 0;
		for (String cur : set) {
			ans[i++] = cur;
		}
		return ans;
	}

	public static void f2(char[] s, int i, char[] path, int size, HashSet<String> set) {
		if (i == s.length) {
			set.add(String.valueOf(path, 0, size));
		} else {
			path[size] = s[i];
			f2(s, i + 1, path, size + 1, set);
			f2(s, i + 1, path, size, set);
		}
	}

}

code2 90. 子集 II

// 给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的组合
// 答案 不能 包含重复的组合。返回的答案中,组合可以按 任意顺序 排列
// 注意其实要求返回的不是子集,因为子集一定是不包含相同元素的,要返回的其实是不重复的组合
// 比如输入:nums = [1,2,2]
// 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
// 测试链接 : https://leetcode.cn/problems/subsets-ii/

package class038;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

// 给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的组合
// 答案 不能 包含重复的组合。返回的答案中,组合可以按 任意顺序 排列
// 注意其实要求返回的不是子集,因为子集一定是不包含相同元素的,要返回的其实是不重复的组合
// 比如输入:nums = [1,2,2]
// 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
// 测试链接 : https://leetcode.cn/problems/subsets-ii/
public class Code02_Combinations {

	public static List<List<Integer>> subsetsWithDup(int[] nums) {
		List<List<Integer>> ans = new ArrayList<>();
		Arrays.sort(nums);
		f(nums, 0, new int[nums.length], 0, ans);
		return ans;
	}

	public static void f(int[] nums, int i, int[] path, int size, List<List<Integer>> ans) {
		if (i == nums.length) {
			ArrayList<Integer> cur = new ArrayList<>();
			for (int j = 0; j < size; j++) {
				cur.add(path[j]);
			}
			ans.add(cur);
		} else {
			// 下一组的第一个数的位置
			int j = i + 1;
			while (j < nums.length && nums[i] == nums[j]) {
				j++;
			}
			// 当前数x,要0个
			f(nums, j, path, size, ans);
			// 当前数x,要1个、要2个、要3个...都尝试
			for (; i < j; i++) {
				path[size++] = nums[i];
				f(nums, j, path, size, ans);
			}
		}
	}

}

code3 46. 全排列

// 没有重复项数字的全排列
// 测试链接 : https://leetcode.cn/problems/permutations/

package class038;

import java.util.ArrayList;
import java.util.List;

// 没有重复项数字的全排列
// 测试链接 : https://leetcode.cn/problems/permutations/
public class Code03_Permutations {

	public static List<List<Integer>> permute(int[] nums) {
		List<List<Integer>> ans = new ArrayList<>();
		f(nums, 0, ans);
		return ans;
	}

	public static void f(int[] nums, int i, List<List<Integer>> ans) {
		if (i == nums.length) {
			List<Integer> cur = new ArrayList<>();
			for (int num : nums) {
				cur.add(num);
			}
			ans.add(cur);
		} else {
			for (int j = i; j < nums.length; j++) {
				swap(nums, i, j);
				f(nums, i + 1, ans);
				swap(nums, i, j); // 特别重要,课上进行了详细的图解
			}
		}
	}

	public static void swap(int[] nums, int i, int j) {
		int tmp = nums[i];
		nums[i] = nums[j];
		nums[j] = tmp;
	}

	public static void main(String[] args) {
		int[] nums = { 1, 2, 3 };
		List<List<Integer>> ans = permute(nums);
		for (List<Integer> list : ans) {
			for (int num : list) {
				System.out.print(num + " ");
			}
			System.out.println();
		}
	}

}

code4 47. 全排列 II

// 有重复项数组的去重全排列
// 测试链接 : https://leetcode.cn/problems/permutations-ii/

package class038;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

// 有重复项数组的去重全排列
// 测试链接 : https://leetcode.cn/problems/permutations-ii/
public class Code04_PermutationWithoutRepetition {

	public static List<List<Integer>> permuteUnique(int[] nums) {
		List<List<Integer>> ans = new ArrayList<>();
		f(nums, 0, ans);
		return ans;
	}

	public static void f(int[] nums, int i, List<List<Integer>> ans) {
		if (i == nums.length) {
			List<Integer> cur = new ArrayList<>();
			for (int num : nums) {
				cur.add(num);
			}
			ans.add(cur);
		} else {
			HashSet<Integer> set = new HashSet<>();
			for (int j = i; j < nums.length; j++) {
				// nums[j]没有来到过i位置,才会去尝试
				if (!set.contains(nums[j])) {
					set.add(nums[j]);
					swap(nums, i, j);
					f(nums, i + 1, ans);
					swap(nums, i, j);
				}
			}
		}
	}

	public static void swap(int[] nums, int i, int j) {
		int tmp = nums[i];
		nums[i] = nums[j];
		nums[j] = tmp;
	}

}

code5 用递归函数逆序栈

// 用递归函数排序栈
// 栈只提供push、pop、isEmpty三个方法
// 请完成无序栈的排序,要求排完序之后,从栈顶到栈底从小到大
// 只能使用栈提供的push、pop、isEmpty三个方法、以及递归函数
// 除此之外不能使用任何的容器,数组也不行
// 就是排序过程中只能用:
// 1) 栈提供的push、pop、isEmpty三个方法
// 2) 递归函数,并且返回值最多为单个整数

package class038;

import java.util.Stack;

// 用递归函数逆序栈
public class Code05_ReverseStackWithRecursive {

	public static void reverse(Stack<Integer> stack) {
		if (stack.isEmpty()) {
			return;
		}
		int num = bottomOut(stack);
		reverse(stack);
		stack.push(num);
	}

	// 栈底元素移除掉,上面的元素盖下来
	// 返回移除掉的栈底元素
	public static int bottomOut(Stack<Integer> stack) {
		int ans = stack.pop();
		if (stack.isEmpty()) {
			return ans;
		} else {
			int last = bottomOut(stack);
			stack.push(ans);
			return last;
		}
	}

	public static void main(String[] args) {
		Stack<Integer> stack = new Stack<Integer>();
		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());
		}
	}

}

code6 用递归函数排序栈

// 用递归函数排序栈
// 栈只提供push、pop、isEmpty三个方法
// 请完成无序栈的排序,要求排完序之后,从栈顶到栈底从小到大
// 只能使用栈提供的push、pop、isEmpty三个方法、以及递归函数
// 除此之外不能使用任何的容器,数组也不行
// 就是排序过程中只能用:
// 1) 栈提供的push、pop、isEmpty三个方法
// 2) 递归函数,并且返回值最多为单个整数

package class038;

import java.util.Stack;

// 用递归函数排序栈
// 栈只提供push、pop、isEmpty三个方法
// 请完成无序栈的排序,要求排完序之后,从栈顶到栈底从小到大
// 只能使用栈提供的push、pop、isEmpty三个方法、以及递归函数
// 除此之外不能使用任何的容器,数组也不行
// 就是排序过程中只能用:
// 1) 栈提供的push、pop、isEmpty三个方法
// 2) 递归函数,并且返回值最多为单个整数
public class Code06_SortStackWithRecursive {

	public static void sort(Stack<Integer> stack) {
		int deep = deep(stack);
		while (deep > 0) {
			int max = max(stack, deep);
			int k = times(stack, deep, max);
			down(stack, deep, max, k);
			deep -= k;
		}
	}

	// 返回栈的深度
	// 不改变栈的数据状况
	public static int deep(Stack<Integer> stack) {
		if (stack.isEmpty()) {
			return 0;
		}
		int num = stack.pop();
		int deep = deep(stack) + 1;
		stack.push(num);
		return deep;
	}

	// 从栈当前的顶部开始,往下数deep层
	// 返回这deep层里的最大值
	public static int max(Stack<Integer> stack, int deep) {
		if (deep == 0) {
			return Integer.MIN_VALUE;
		}
		int num = stack.pop();
		int restMax = max(stack, deep - 1);
		int max = Math.max(num, restMax);
		stack.push(num);
		return max;
	}

	// 从栈当前的顶部开始,往下数deep层,已知最大值是max了
	// 返回,max出现了几次,不改变栈的数据状况
	public static int times(Stack<Integer> stack, int deep, int max) {
		if (deep == 0) {
			return 0;
		}
		int num = stack.pop();
		int restTimes = times(stack, deep - 1, max);
		int times = restTimes + (num == max ? 1 : 0);
		stack.push(num);
		return times;
	}

	// 从栈当前的顶部开始,往下数deep层,已知最大值是max,出现了k次
	// 请把这k个最大值沉底,剩下的数据状况不变
	public static void down(Stack<Integer> stack, int deep, int max, int k) {
		if (deep == 0) {
			for (int i = 0; i < k; i++) {
				stack.push(max);
			}
		} else {
			int num = stack.pop();
			down(stack, deep - 1, max, k);
			if (num != max) {
				stack.push(num);
			}
		}
	}

	// 为了测试
	// 生成随机栈
	public static Stack<Integer> randomStack(int n, int v) {
		Stack<Integer> ans = new Stack<Integer>();
		for (int i = 0; i < n; i++) {
			ans.add((int) (Math.random() * v));
		}
		return ans;
	}

	// 为了测试
	// 检测栈是不是从顶到底依次有序
	public static boolean isSorted(Stack<Integer> stack) {
		int step = Integer.MIN_VALUE;
		while (!stack.isEmpty()) {
			if (step > stack.peek()) {
				return false;
			}
			step = stack.pop();
		}
		return true;
	}

	// 为了测试
	public static void main(String[] args) {
		Stack<Integer> test = new Stack<Integer>();
		test.add(1);
		test.add(5);
		test.add(4);
		test.add(5);
		test.add(3);
		test.add(2);
		test.add(3);
		test.add(1);
		test.add(4);
		test.add(2);
		sort(test);
		while (!test.isEmpty()) {
			System.out.println(test.pop());
		}

		// 随机测试
		int N = 20;
		int V = 20;
		int testTimes = 20000;
		System.out.println("测试开始");
		for (int i = 0; i < testTimes; i++) {
			int n = (int) (Math.random() * N);
			Stack<Integer> stack = randomStack(n, V);
			sort(stack);
			if (!isSorted(stack)) {
				System.out.println("出错了!");
				break;
			}
		}
		System.out.println("测试结束");
	}

}

code7 打印n层汉诺塔问题的最优移动轨迹

// 打印n层汉诺塔问题的最优移动轨迹

package class038;

// 打印n层汉诺塔问题的最优移动轨迹
public class Code07_TowerOfHanoi {

	public static void hanoi(int n) {
		if (n > 0) {
			f(n, "左", "右", "中");
		}
	}

	public static void f(int i, String from, String to, String other) {
		if (i == 1) {
			System.out.println("移动圆盘 1 从 " + from + " 到 " + to);
		} else {
			f(i - 1, from, other, to);
			System.out.println("移动圆盘 " + i + " 从 " + from + " 到 " + to);
			f(i - 1, other, to, from);
		}
	}

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

}

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

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

相关文章

c++搭建http服务器

HTTP请求协议格式如下&#xff1a; HTTP响应协议格式如下&#xff1a; #include <iostream> #include <winsock2.h> #include <ws2tcpip.h> #include <string>#pragma comment(lib, "ws2_32.lib")//std::string generateResponse(const st…

华为OD机试 - 九宫格按键输入 - 逻辑分析(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

固定Microsoft Edge浏览器的位置设置,避免自动回调至中国

问题描述 在使用Copilot等功能时&#xff0c;需要将Microsoft Edge浏览器的位置设置为国外。但每次重新打开浏览器后&#xff0c;位置设置又自动回调至中国&#xff0c;导致每次均需要手动调整。 原因分析 这个问题的出现是因为每次启动Microsoft Edge时&#xff0c;默认打开…

【开源】基于Vue+SpringBoot的网上药店系统

项目编号&#xff1a; S 062 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S062&#xff0c;文末获取源码。} 项目编号&#xff1a;S062&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 药品类型模块2.3 药…

6 大 Android 照片恢复软件深度评测

当您发现令人难忘的照片在 Android 上被错误删除或丢失时&#xff0c;您可能会感到非常沮丧。然而&#xff0c;当您尝试安装一些恢复应用程序并希望将它们重新恢复时&#xff0c;其中许多应用程序无法再次检测到丢失的照片。 为了节省您逐一尝试此类应用程序的时间&#xff0c…

【华为OD题库-076】执行时长/GPU算力-Java

题目 为了充分发挥GPU算力&#xff0c;需要尽可能多的将任务交给GPU执行&#xff0c;现在有一个任务数组&#xff0c;数组元素表示在这1秒内新增的任务个数且每秒都有新增任务。 假设GPU最多一次执行n个任务&#xff0c;一次执行耗时1秒&#xff0c;在保证GPU不空闲情况下&…

对标Gen-2!Meta发布新模型进军文生视频赛道

随着扩散模型的飞速发展&#xff0c;诞生了Midjourney、DALLE 3、Stable Difusion等一大批出色的文生图模型。但在文生视频领域却进步缓慢&#xff0c;因为文生视频多数采用逐帧生成的方式,这类自回归方法运算效率低下、成本高。 即便使用先生成关键帧,再生成中间帧新方法。如…

分类信息发布小程序效果如何

信息发布系统连接信息供需双方&#xff0c;打造信息聚合平台&#xff0c;用户可获取和发布需求信息、参与互动交流&#xff0c;适用于同城、社区交流、客户互动、业务员/经纪人发布信息场景。 制作分类信息小程序后&#xff0c;商家后台设置信息项&#xff0c;发布者填写内容发…

java 产品定制服务系统myeclipse开发sqlserver数据库BS模式java编程

一、源码特点 java 产品定制服务系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;比较流行的ssh框架系统具有完整的源代码和数据库&#xff0c;myeclipse开发系统主要采用B/S模式开发 。 javaWeb产品定制服务系统1 二、功能介绍 前台功…

好用的音乐制作工具 Studio One 6中文 for mac

Studio One 6是一款专业的音乐制作软件&#xff0c;提供了全面而强大的功能&#xff0c;帮助音乐制作人、录音工程师和创作者实现他们的创意。 它的主要特点包括&#xff1a;直观的用户界面&#xff0c;使得操作变得简单易懂&#xff1b;支持多轨录音&#xff0c;允许用户进行…

Altair推出 Altair RapidMiner 2023 平台,提供生成式 AI 功能

Altair推出 Altair RapidMiner 2023 平台&#xff0c;提供生成式 AI 功能 更新包括自动聚类、扩展 SAS、Python 和 R 编程功能等 近日&#xff0c;Altair&#xff08;纳斯达克股票代码&#xff1a;ALTR&#xff09;近日宣布其数据分析和 AI 平台 Altair RapidMiner 取得了一系…

深度学习 -- 神经网络

1、神经网络的历史 2、 M-P模型 M-P模型是首个通过模仿神经元而形成的模型。在M-P模型中,多个输入节点对应一个输出节点y。每个输入x,乘以相应的连接权重w,然后相加得到输出y。结果之和如果大于阈值h,则输出1,否则输出0。输入和输出均是0或1。 公式2.1&#xff1a; …

基于ssm+jsp的精品酒销售管理系统论文

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于精品酒销售管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了精品酒销售管理系统&#xff0c;它彻底改变…

MyBatisPlus+SpringBoot+JavaFX连接查询

前言 一般使用SprootBoot是使用SprootBootTest和Junit配合&#xff0c;但如果不是写测试类&#xff0c;怎么与javafx配合使用&#xff1f;笔者不知道&#xff0c;经过多次搜索以及问了各种AI&#xff0c;最后误打误撞&#xff0c;终于想通了&#xff0c;其实很简单。 用了许久…

碳信用市场的未来:中碳CCNG的愿景

在全球碳减排努力日益增强的背景下&#xff0c;中国碳中和发展集团有限公司&#xff08;简称中碳CCNG&#xff09;正以其创新的碳交易平台引领行业新趋势。中碳CCNG提供的一站式综合服务不仅包括碳信用的托管、买卖和抵消&#xff0c;而且通过其综合性数字平台&#xff0c;促进…

【CodeTop】TOP 100 刷题 31-40

文章目录 31. 二叉树中的最大路径和题目描述代码与解题思路 32. 合并区间题目描述代码与解题思路 33. 编辑距离题目描述代码与解题思路 34. 二叉树的中序遍历题目描述代码与解题思路 35. 最长公共子序列题目描述代码与解题思路 36. 二分查找题目描述代码与解题思路 37. 二叉树的…

STM32F407-14.3.13-01发生外部事件时清除 OCxREF 信号

发生外部事件时清除 OCxREF 信号 对于给定通道&#xff0c;在 ETRF⑧ 输入施加高电平&#xff08;相应 TIMx_CCMRx 寄存器中的 OCxCE⑦ 使能位置“1”&#xff09;&#xff0c;可使 OCxREF⑨ 信号变为低电平。OCxREF⑨ 信号将保持低电平&#xff0c;直到发生下一更新事件 (UEV)…

SAM+使用SAM应用数据集完成分割

什么是SAM&#xff1f; SAM(Segment Anything Model&#xff09;是由 Meta 的研究人员团队创建和训练的深度学习模型。在 Segment everything 研究论文中&#xff0c;SAM 被称为“基础模型”。 基础模型是在大量数据上训练的机器学习模型&#xff08;通常通过自监督或半监督学习…

农业杀虫剂市场分析:我国实现销售收入319.3亿元

农业杀虫剂&#xff0c;指的是农业用的杀虫化学制剂。主要用于防治农业害虫和城市卫生害虫的药品&#xff0c;使用历史长远、用量大、品种多。 按毒理作用可分为&#xff1a;①神经毒剂。作用于害虫的神经系统&#xff0c;如滴滴涕、对硫磷、呋喃丹、除虫菊酯等。②呼吸毒剂。抑…

ssm党务政务服务热线平台源码和论文答辩PPT

摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计…