Recursion 求所有子集 @CareerCup

【Python】Recursion递归 典型问题 ~~ 【Python】Recursion 典型问题 这里是一个刚刚上手Python的小白整理的一些题型。期末考试将至,供复习之用。 部分题型及代码来源于网络,某些部分进行了适当的修改,如有侵权请尽快联系我哦~ ~~ 1. 二分法找有序数列指定值 def dichotomy(min, max, d, n): '''初始mid=0, max=len(d)''' mid = (min+max)/... 阅读详情

这道题可以用递归和迭代两种方法来做。


先说一下有收获的地方:

在递归中,更经常的采用的是头递归,即调用先递归处理子问题,然后基于子问题的解再处理当前问题!并且这样还能减少stack中保存的内容。

当然如果是比较简单的递归,即当前问题不依赖于子问题的解,如前面的那道findMagicIndex问题,就可以用尾递归。


还有一点是,

因为我在递归中ret值是不断往下传递的,所以如果不注意就可能造成concurrency exception。因此要预先计算好ret的size保存在一个变量中,而不能在for中每次去查询ret的size,因为随着不断增加入元素,size每次就都会变!


下面说一下两种思路,http://hawstein.com/posts/8.3.html 写的很好,直接搬过来。。


递归思路:

这道题目为什么可以用递归? 因为我们能找到比原问题规模小却同质的问题。比如我要求{1, 2, 3}的所有子集, 我把元素1拿出来,然后去求{2, 3}的所有子集,{2, 3}的子集同时也是{1, 2, 3} 的子集,然后我们把{2, 3}的所有子集都加上元素1后,又得到同样数量的子集, 它们也是{1, 2, 3}的子集。这样一来,我们就可以通过求{2, 3}的所有子集来求 {1, 2, 3}的所有子集了。而同理,{2, 3}也可以如法炮制。


迭代思路:

对于一个集合,它的子集一共有2n 个(包括空集和它本身)。它的任何一个子集, 我们都可以理解为这个集合本身的每个元素是否出现而形成的一个序列。比如说, 对于集合{1, 2, 3},空集表示一个元素都没出现,对应{0, 0, 0}; 子集{1, 3},表示元素2没出现(用0表示),1,3出现了(用1表示),所以它对应 {1, 0, 1}。这样一来,我们发现,{1, 2, 3}的所有子集可以用二进制数000到111 的8个数来指示。泛化一下,如果一个集合有n个元素,那么它可以用0到2n -1 总共2n 个数的二进制形式来指示。每次我们只需要检查某个二进制数的哪一位为1, 就把对应的元素加入到这个子集就OK。


package Recursion;

import java.util.ArrayList;

/**
 *  Write a method that returns all subsets of a set.
 *  
 *  写一个函数返回一个集合中的所有子集。
 *
 */
public class S9_4 {

	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<Integer>();
		for (int i = 0; i < 3; i++) {
			list.add(i);
		}
		ArrayList<ArrayList<Integer>> subsets = getSubsets2(list, 0);
		System.out.println(subsets.toString());
		
		ArrayList<ArrayList<Integer>> subsets2 = getSubsetIter(list);
		System.out.println(subsets2.toString());		
	}

	public static ArrayList<ArrayList<Integer>> getSubsets(ArrayList<Integer> list, int start) {
		ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
		rec(list, start, ret);
		return ret;
	}
	
	// 递归方法,把第一个元素加到子问题返回的每一个子集中
	public static void rec(ArrayList<Integer> list, int start, ArrayList<ArrayList<Integer>> ret){
		if(start == list.size()){
			ret.add(new ArrayList<Integer>());
			return;
		}
		
		rec(list, start+1,ret);			// 头递归!必须是基于子问题的答案来处理当前问题!
		int head = list.get(start);		
		int size = ret.size();				// 注意不能用foreach来做,也不能直接把ret.size()放在for循环中,否则每次都改变ret的长度
												// 会得到ConcurrentModificationException或者直接耗尽内存
		for (int i=0; i<size; i++) {
			ArrayList<Integer> nal = new ArrayList<Integer>(ret.get(i));
			nal.add(head);
			ret.add(nal);
		}
	}
	
	// 利用二进制的表示来做,0表示不取,1表示取
	public static ArrayList<ArrayList<Integer>> getSubsetIter(ArrayList<Integer> list) {
		int len = list.size();
		ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
		for(int i=0; i<Math.pow(2, len); i++){		// 子集的总数是2^len个
			int tmp = i;
			ArrayList<Integer> al = new ArrayList<Integer>();
			int index = 0;
			while(tmp != 0){
				if((tmp & 1) != 0){			// 如果最后一位是1,则取
					al.add(list.get(index));
				}
				tmp >>= 1;						// 不断右移直到为0
				index++;
			}
			ret.add(al);
		}
		return ret;
	}
	
	
	
	public static ArrayList<ArrayList<Integer>> getSubsets2(ArrayList<Integer> list, int start) {
		ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
		rec2(new ArrayList<Integer>(), new ArrayList<Integer>(list), ret);
		return ret;
	}

	// 每个元素都有取或者不取两种状态,因此对两种状态分别递归
	/*
	 * (,abc):
	 * 
	 * (a,bc)
	 * 		(ab,c)
	 * 			(abc,)
	 * 			(ab,)
	 * 		(a,c)
	 * 			(ac,)
	 * 			(a,)
	 * 
	 * (,bc)
	 * 		(b,c)
	 * 			(bc,)
	 * 			(b,)
	 * 		(,c)
	 * 			(c,)
	 * 			(,)
	 * 
	 */
	public static void rec2(ArrayList<Integer> done, ArrayList<Integer> rest, ArrayList<ArrayList<Integer>> ret){
		if(rest.size() == 0){
			ret.add(new ArrayList<Integer>(done));		// 必须创建新数组保存状态!
			return;
		}
		
		Integer val = rest.get(0);		// 取得头元素		
		rest.remove(0);					// 更新rest
		
		done.add(val);					// 一种是取的状态
		rec2(done, rest, ret);
		done.remove(done.size()-1);		// 要记得恢复现场
		
		rec2(done, rest, ret);		// 另一种是不取的状态

		rest.add(0, val);				// 要记住恢复现场!
	}
}





两种求集合所有子集的方法 假设我们有一个求集合的全部子集(包含集合自身)的需求,即有一个集合s,包含两个元素 ,则其全部的子集为. 不难求得,子集个数sn与原集合元素个数n之间的关系为:sn=2^n-1。   本文分别讲述两种实现方法:   一:位图法: 1)构造一个和集合一样大小的数组A,分别与集合中的某个元素对应,数组A中的元素只有两种状态:“1”和“0”,分别代表每次子集输出中集合中对应元素是否要输出,这 阅读详情

相关推荐

Vector CANape的使用记录

开门见山,今天想和大家分享下CANape使用记录,分享原因是近日在分析一个客户现场软件问题时,需要用到CANape来实时的监测ECU中的变量,因为之前对CANape的认知比较浅薄,觉得标定工程师使用他就足够了,但是这次的经历让我觉得需要写点东西来记录自己学习并使用他的过程。 相信大家能够在网上找到很多关于如何使用CANape的文章,从新建Project到后面的数据的观测、保存以及回放等等。我个人也是这么学过来的,所以我不打算从那些方面着手去描述如何使用她,而是根据我的真实使用过程以及问题的抛出到如何解决来

2万+

《数据结构、算法与应用》5.(递归输出n个元素的所有子集)

最近在读《数据结构、算法与应用》这本书,把书上的习题总结一下,用自己的方法来实现了这些题,可能在效率,编码等方面存在着很多的问题,也可能是错误的实现,如果大家在看这本书的时候有更优更好的方法来实现,还请大家多多留言交流多多指正,谢谢  5. 试编写一个递归函数,用来输出n 个元素的所有子集。      例如,三个元素{a, b, c} 的所有子集是: { }(空集),{ a }, { b },

CC专栏 2825

LangFlow开源神器:拖拽构建AI Agent与MCP协议集成实战

LangFlow 15万星开源神器:拖拽搭建 AI Agent,一键部署 API / MCP / JSON 在AI应用开发领域,传统编码方式往往需要处理复杂的API调用、数据处理和流程编排,这让很多开发者望而却步。LangFlow作为GitHub上获得15万星的开源项目,通过可视化拖拽的方式彻底改变了AI Agent的开发体验。本文将完整介绍如何使用LangFlow快速构建功能强大的AI Agent,并实现API、MCP协议和JSON配置的一键部署。 1. LangFlow与AI Agent核心概念解析 1

weixin_33717117的博客 934

求所有子数组的和的最大值。要求时间复杂度为O(n)

题目:输入一个整形数组,数组里有正数也有负数,

iris0802的专栏 1707

如何利用VS2017创建一个简单的窗口

#如何利用VS2017创建一个简单的窗口 1、新建->Windows桌面向导 2、应用程序类型->桌面应用程序,点击确定 3、点击调试->开始调试 可建立如下图的窗口 4、可以在生成的项目文件的中找到windows17_2的应用程序,打开界面如下: 注:新建空白项目也可以,注意在解决方案资源器中添加.cpp文件,如源.cpp文件,下载代码见博文 ...

weixin_46894139的博客 2914

temu登录接口逆向分析(含Py纯算)

【代码】temu登录接口逆向分析(含Py纯算)

数据精灵喵 1944

求集合的所有子集的算法(C++)

  求集合的所有子集的算法 对于任意集合A,元素个数为n(空集n=0),其所有子集的个数为2^n个 如集合A={a,b,c},其子集个数为8;对于任意一个元素,在每个子集中, 要么存在,要么不存在,对应关系是: a-&gt;1或a-&gt;0 b-&gt;1或b-&gt;0 c-&gt;1或c-&gt;0 映射为子集: (a,b,c) (1,1,1)-&gt;(a,b...

mare2012的博客 4266

避坑指南:PCIe设备兼容性那些坑——聊聊MPS/MRRS设置不当引发的血泪史

本文深入探讨了PCIe设备兼容性问题,特别是MPS/MRRS参数设置不当引发的常见故障。通过详细解析MPS(Max Payload Size)和MRRS(Max Read Request Size)的作用机制,提供Linux内核五大配置策略的对比分析,并分享FPGA加速卡等实战案例的排查经验。文章还介绍了诊断工具链、动态调试技巧以及性能优化方法,帮助工程师有效解决PCIe兼容性难题。

weixin_30872499的博客 419

python编程题:字符串的(所有可能的)排列组合

在此研究: 1)给定一个字符串,如何对其中字母进行排列组合; 2)进一步了解Python递归。

the Blog of 等不到天亮丶等时光 2万+

【YOLOv11】014、YOLOv11模型导出:PyTorch到ONNX格式转换与优化

摘要:本文详细介绍了如何将PyTorch训练的YOLOv11模型高效转换为ONNX格式。重点包括:分离模型特征提取与后处理、设置动态维度、优化ONNX算子、验证转换正确性等关键步骤。作者分享了实际项目中的经验教训,如版本对齐、算子兼容性处理、后处理分离等实用技巧,并推荐使用onnx-simplifier工具优化模型。文章强调模型转换是一个需要反复调试的过程,建议保留转换记录形成知识库,以提高部署效率并避免常见错误。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 305

【云原生技术】SonarQube 生态中PMD插件和P3C插件详细介绍

4. 在项目中如何选择 / 组合 1. 小团队、对《阿里规约》认同度高 → 直接启用 **P3C**,配合 SonarJava 基本够用。 2. 追求全面 Bug/安全检测 + 额外编码规范 → **SonarJava + PMD**(必要时加 P3C 少量规则)。 3. 大型多团队,希望“一本规约”统一风格 → **P3C 为主**,再补充 SonarJava/PMD 的 Bug 与安全规则。 4. 通过 Quality Gate 控制:将 **Blocker/Critical** Bug

weixin_46453070的博客 1365

输出一个集合的所有子集(算法)

转自输出一个集合的所有子集(算法) 时间复杂度很显然,最少也是2^n,空间复杂度,是n,代码比较简单(每个元素要么在子集中,要么不在,用 j 的二进制形式的每一位代表数组a中对应的位置的元素是否在子集中,例如,当i = 5时, j = i = 5,那么j = 0101; 我们对应的输出 a[0], a[2], 这个过程在while循环中完成) [cp...

weixin_30394251的博客 1144

Pytorch实现之SRGAN+CBAM的结构设计

在SRGAN的残差连接中加入了CBAM注意力机制,同时设计了四类损失来训练。

LJ1147517021的博客 569

Recursion n对括号的组合 @CareerCup

看不太习惯书上写的递归,觉得没有自己写的清晰。 这道题唯一要满足的条件就是在任何时候,左括号数量一定要大等于右括号的数量。 package Recursion; import java.util.HashSet; import java.util.Set; /** *Implement an algorithm to print all valid (e.g., properly

1779

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Recursion 在数组中寻找神奇下标 @CareerCup

当数组里的元素没有重复时,因为数组已经是排序好的了,自然想到用二分法。 如果数组里的元素有重复时,magic index可能出现在左侧也可能出现在右侧,这个画图举个例子就知道了。 可以优化的是,无论是在左侧还是右侧,总有一些元素可以直接排除,从而缩短查找时间! package Recursion; import java.util.Arrays; import CtCILibra

1963

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Recursion 叠箱子最高问题 @CareerCup

这类问题要多多画图 package Recursion; import java.util.ArrayList; import java.util.HashMap; /** * You have a stack of n boxes, with widths wi, heights hi and depths di The * boxes cannot be rotated an

2226

Recursion 爬楼梯问题 @CareerCup

开始CareerCup一书的刷题。。先从recursion这一章开始! 我的解法: package Recursion; /** * A child is running up a staircase with n steps, and can hop either 1 step, 2 * steps, or 3 steps at a time. Implement a meth

2074

Recursion 字符串的全排列 String Permutation @CareerCup

字符串全排列的题目,还是套用模板,同样要注意ret的size问题会变化。而且与上一题不同的是不光是要在ret后面添加进新的组合,而且还要移除前面用过的组合。类似一个队列。 另外Java的substring中区间闭合情况是左闭右开 [ ) 所以想把一个字符串拆成两个区间就可以用这一句: for(int j=0; j<=tmp.length(); j++){ // substring

2977

Recursion 计算表达式的括号组合 @CareerCup

还没细看,先把代码放在这里 package Recursion; import java.util.HashMap; /** * Given a boolean expression consisting of the symbols 0,1, &, /, and ^ , and a * desired boolean result value result, implement

1679

Recursion 硬币组合问题 @CareerCup

非常有意义的一道题,关键的一点要知道DFS是有顺序的,即在DFS中(5,1)和(1,5)是不一样的组合。所以对这道题我的第一种解法就重复算了多次,具体如图所示:当计算f(10)时,DFS给出的结果是9次,但实际上应该是4. 去重的方法是多用一个变量(level)来限制条件。这样能保证在访问对于给定level只会深搜小于等于level的分支。 同样参考了http://hawstein.c

2366

Recursion 八皇后问题 @CareerCup

递归+回溯,不多说了。唯一要注意的是在每次记录一个可行的方案时,要复制一份数组,在Java中可以通过 1 循环复制 2 clone() 方法 3 System.arraycopy() 方法 这里按照书上,用了clone()方法! package Recursion; import java.util.ArrayList; /** * Write an algorithm t

1356

Recursion 图像软件中的“填充”函数 @CareerCup

搞清楚题意后就很简单了,用DFS暴搜即可 package Recursion; /** * 原文: Implement the “paint fill” function that one might see on many image editing programs. That is, given a screen (represented by a 2-dimensiona

2049

Recursion 二维空间里机器人向右或向下走的所有路径问题 @CareerCup

这道题学到了在做回溯时,先把点加入到path中,然后根据子情况来决定success这个变量,从而决定之前加入的点是否有必要的。如果子情况返回的是false,则这个点也没有必要加入到path中,就可以移除了。 还有一个是,我的解答中每次函数只对当前点进行isFree的判断,官方答案中却对下一个节点进行判断。我还是觉得我的更直观一些。 package Recursion; import

1918

java递归获取所有子级存到集合

java递归获取 父级下的所有子级项目需求表结构代码 项目需求 一个公司要获取到这个公司下的所有子公司,很多日志都是通过递归获取下级构成树形结构但是我这个不需要树形结构,是获取到所有子级放到集合中方便遍历 如图 表结构 代码 private List<HjTManagement> selectHjTManagementListByPid(Long managementAreaId){ List<HjTManagement> list = new ArrayLi

才这么点的博客 5692

Leetcode:Subsets 求数组的所有子集

Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be in non-descending order.The solution set must not contain duplicate subsets. For exa

littlebirdman的专栏 1万+

9.9递归和动态规划(四)——返回某集合的所有子集

/**  * 功能:返回某集合的所有子集。  */ 三种方法: 方法一:迭代 //迭代 /** * 注意:每次加入集合后会改变原来的集合,无法继续从集合中取出元素。 * 必须通过一个中间参数moreSubsets来保存中间结果,最后加入allSubsets。 * @author Lynne * @param set * @param index *

shangqing1123的博客 1374
上一篇: Recursion 在数组中寻找神奇下标 @CareerCup
下一篇: Recursion 字符串的全排列 String Permutation @CareerCup
chiiis
博客等级 码龄14年 422粉丝 429原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值