题目:给定一个集合,求该集合的所有子集合,如集合{1,2}的子集合有{}(空集是所有集合的子集),{1},{2},{1,2},共2^2个子集合,下面给出两种解法,其中第一种解法分递归与非递归实现,都用java实现。
【第一种解法】
算法思想:给定一个集合,求子集合过程可分为以下两个步骤:
(1)把集合分为两部分,第一个元素和剩余元素,如{1,2,3}分为1和{2,3}
(2)原集合的所有子集合为剩余元素的子集合并上把第一个元素加入所有子集合,如{2,3}的子集合为{2},{3},{2,3},{},那么把第一个元素1加入这些子集合,则构成{1,2},{1,3},{1,2,3},{1},把这些集合合并起来,则原集合的所有子集合便为{2},{3},{2,3},{},{1,2},{1,3},{1,2,3},{1},代码如下:
【非递归实现】
package bitSet; import java.util.ArrayList; public class SubSet { public static void main(String[] args) { int array[] = { 1, 2, 3, 4, 5, 6 }; ArrayList<ArrayList<Integer>> allSet = new ArrayList<ArrayList<Integer>>(); allSet.add(new ArrayList<Integer>()); for (int i = 0; i < array.length; i++) { ArrayList<ArrayList<Integer>> subSet = new ArrayList<ArrayList<Integer>>(); for (int j = 0; j < allSet.size(); j++) { ArrayList<Integer> element = new ArrayList<Integer>(); element.add(array[i]); element.addAll(allSet.get(j)); subSet.add(element); } allSet.addAll(subSet); } int count = 0; for (int i = 0; i < allSet.size(); i++) { ArrayList el = allSet.get(i); for (int j = 0; j < el.size(); j++) { System.out.print(el.get(j) + " "); } count++; System.out.println(); } System.out.println(count); } }
【递归实现】
package bitSet; import java.util.ArrayList; public class SubSet1 { static ArrayList<ArrayList<Integer>> getSubsets(int[] set, int index) { ArrayList<ArrayList<Integer>> allsubsets; if (set.length == index) { allsubsets = new ArrayList<ArrayList<Integer>>(); allsubsets.add(new ArrayList<Integer>()); // Empty set } else { allsubsets = getSubsets(set, index + 1); int item = set[index]; ArrayList<ArrayList<Integer>> moresubsets = new ArrayList<ArrayList<Integer>>(); for (ArrayList<Integer> subset : allsubsets) { ArrayList<Integer> newsubset = new ArrayList<Integer>(); newsubset.addAll(subset); // newsubset.add(item); moresubsets.add(newsubset); } allsubsets.addAll(moresubsets); } return allsubsets; } public static void main(String[] args) { int array[] = { 1, 2, 3, 4, 5, 6 }; ArrayList<ArrayList<Integer>> allSet = getSubsets(array,0); int count = 0; for (int i = 0; i < allSet.size(); i++) { ArrayList el = allSet.get(i); for (int j = 0; j < el.size(); j++) { System.out.print(el.get(j) + " "); } count++; System.out.println(); } System.out.println(count); } }
【第二种解法】
算法思想:n个元素的集合,在构造子集合过程中,每个元素有两种情况,在子集合中“存在”与“不存在”,“存在”用“1”表示,“不存在”用“0”表示,这样共有2^n种情况,即2^n个子集合。此时我们想到用长度为n的二进制数字 “1111....000...”,1表示该位置在子集合中存在,0表示该位置在子集合中不存在,让该二进制数从0 一直加到 2^n,则所有情况都会出现,代码如下
package bitSet; import java.util.ArrayList; public class SubSet3 { static ArrayList<ArrayList<Integer>> getSubsets(int[] set) { ArrayList<ArrayList<Integer>> allsubsets = new ArrayList<ArrayList<Integer>>(); int max = 1 << set.length; for (int i = 0; i < max; i++) { ArrayList<Integer> subset = new ArrayList<Integer>(); int k = i; int index = 0; while (k > 0) { if ((k & 1) > 0) { subset.add(set[index]); } k >>= 1; index++; } allsubsets.add(subset); } return allsubsets; } public static void main(String[] args) { int array[] = { 1, 2, 3, 4, 5, 6 }; ArrayList<ArrayList<Integer>> allSet = getSubsets(array); int count = 0; for (int i = 0; i < allSet.size(); i++) { ArrayList el = allSet.get(i); for (int j = 0; j < el.size(); j++) { System.out.print(el.get(j) + " "); } count++; System.out.println(); } System.out.println(count); } }
相关推荐
根据提供的代码片段,我们可以看到这是一个使用递归方式实现的求子集算法。下面将对这段代码进行逐行分析: 1. **头文件包含**: ```cpp #include #include ``` - `#include<iostream>`:用于输入输出操作。 ...
在这个“java集合框架的使用”主题中,我们将深入探讨如何利用Java集合框架进行基本的集合运算,包括散列集合、求子集以及集合的交和并。 首先,我们要理解Java集合框架的基本层次结构。它主要包括接口(如List、...
求子集问题--一个ACM程序竞赛题 本文将详细讲解求子集问题,这是一个ACM程序竞赛题。...本文讲解了求子集问题的解决方法,包括递推思想、栈和递归实现、算法评价、递归程序的实现和时间复杂度等知识点。
从X{a1,a2,a3,...,an}集合用回溯法按照升序或降序找出和的第一个子集,可设置最大求解时间。
位运算是指在计算机科学领域,直接对整数(通常是二进制表示)的二进制位进行操作的一种计算方式。常用的位运算包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移()和右移(>>)等。这些运算通常具有高效性,...
在离散数学中,集合是一组不重复的元素,它具有特定的运算,如并集、交集、差集和笛卡尔积等。...这些示例代码是学习和理解集合操作在C语言中实现的好资源,可以帮助提升编程技能,特别是对数据结构和算法的理解。
回溯法是一种在搜索解决问题时,通过尝试所有可能的解决方案并逐步缩小问题规模来找到答案的算法。在解决“求集合的子集”问题时,它特别有效,尤其是在集合元素数量较小,例如n的情况下。这个任务的目标是生成一个...
总的来说,求集合所有子集问题是组合问题的经典实例,递归算法提供了一种直观的解决方案。通过理解和掌握这种方法,不仅可以解决这类问题,还能加深对递归以及算法设计的理解。在实际编程中,还可以结合其他数据结构...
回溯法是一种强大的算法策略,常用于解决组合优化问题,如子集和问题。这个问题的目标是从给定的一组整数中找出所有可能的子集,使得这些子集的元素和等于一个特定的目标值。在本案例中,我们将深入探讨如何使用回溯...
在代码中,线性表是通过结构体list实现的,包含了指向数据结点的指针p,当前顺序表长度length和当前分配的线性表长度listsize三个成员变量。 线性表的操作包括初始化、销毁、清空、判断是否为空、获取元素、获取...
本压缩包文件"商业编程-源码-树控件的应用 求子树节点的集.zip"主要关注的是如何在编程中实现对树控件的子节点集合的操作,特别是查找子树节点的功能。以下将详细介绍这个知识点,并提供相关的编程概念和技术。 ...
【算法面试题21】是针对程序员面试时常见的算法题目集合,主要考察的是思维能力和算法应用。以下将详细解析这些题目: 1. **二元查找树转双向链表**: 这个问题要求将一棵二元查找树(BST)转换成一个有序的双向...
求子数组和的最大值 power函数的实现 10次90环的组合数 有两个整形数组,交换两个数组的元素使得两个元素和的差最小 打印幻方 走方格 求数对之差最大值 现有整型数组{1,2,4,3,5,8},写出一个函数,找出...
1.2. 面试题集合(一) .......................................................................................... 8 1.2.1. 把二元查找树转变成排序的双向链表................................................
根据给定的文件信息,我们可以总结出以下关键的知识点,这些知识点主要围绕“微软等公司数据结构+算法面试100题”的主题展开,旨在帮助求职者准备IT行业的技术面试,特别是聚焦在数据结构和算法方面。 ### 1. 数据...
微软公司等数据结构+算法面试题集合概述: 微软等公司数据结构+算法面试100题的首次完整亮相,主要涉及数据结构和算法两大IT领域的核心知识点。该系列题目覆盖了众多技术要点,包括但不限于二元查找树、双向链表、栈...
【算法100题(C/C++)】是一系列旨在提升编程能力,特别是算法设计和实现的题目集合,适合准备IT互联网公司的面试。以下是一些题目详解: 1. **二元查找树转双向链表**: - 二元查找树是一种自平衡的搜索树,其特点...
ADT是一种设计方法,允许程序员根据问题的需求设计数据结构,而不必立即考虑这些数据结构在计算机内存中的具体实现。 3. 线性表及其操作 线性表是数据元素按照线性顺序排列的数据结构,它可以用数组或链表的形式...
在编程领域,子集和问题是一个经典的问题,它涉及到算法设计和实现,特别是与动态规划或回溯法相关的策略。本项目是用C++语言在Visual Studio 2010环境下开发的一个程序,用于解决此类问题。下面我们将深入探讨这个...
文档标题为“微软数据结构算法面试题”,描述提到这是一个关于微软等数据结构与算法面试的100题集合,以PDF形式呈现。这份资料由作者July于2010年12月6日最终完成,包含了精心整理的100个数据结构和算法面试题目及其...