`
MouseLearnJava
  • 浏览: 467284 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

根据数组数据,得到和一定的所有子集

    博客分类:
  • Java
 
阅读更多
给定一个数字数组,设定一个目标值, 然后以这个数组为数据源,要求给出所有的子集,这些子集中数据的和要等于设定的目标值。例如: 数字数组: [1,2,3,4,5,6] 目标值为 7 那么,所有和为7的子集有[1,2,4] [3,4]......

import java.util.Stack;

/**
 * 给定一个数字数组,设定一个目标值, 然后以这个数组为数据源,要求给出所有的子集,这些子集中数据的和要等于设定的目标值。
 * 
 * 例如: 数字数组: [1,2,3,4,5,6] 目标值为 7 那么,所有和为7的子集有[1,2,4] [3,4]......
 * 
 * 本例子中采用了Stack来实现, 提供了两个public方法:
 * 1. 用于输出所有符合条件的结果
 * 2. 可以设定子集中的元素的个数范围,从而输出符合此条件的子集
 * 
 * @author Eric
 * @version 1.0
 * 
 */

public class PopulateSubsetByStack {

	private Stack<Integer> stack = new Stack<Integer>();

	// 用于字符串的相加
	private StringBuilder sb = new StringBuilder();

	public void populateSubset(int[] values, int begin, int end,
			int sumInStack, int expectedSum) {

		/*
		 * 判断Stack中的数据和是否等于目标值,如果是则输出当前Stack中的数据
		 */
		if (sumInStack == expectedSum) {
			print(stack, expectedSum);
		}

		for (int currentIndex = begin; currentIndex < end; currentIndex++) {
			/*
			 * 如果当前Stack中的和加上当前index的数据小于等于目标值, 那么将当前的index的数据添加到Stack中去,
			 * 同时,将当前Stack中所有数据的和加上新添加到Stack中的数值
			 */
			if (sumInStack + values[currentIndex] <= expectedSum) {
				stack.push(values[currentIndex]);
				sumInStack += values[currentIndex];
				// 当前index加上1,递归调用本身
				populateSubset(values, currentIndex + 1, end, sumInStack,
						expectedSum);

				sumInStack -= stack.pop();
			}

		}
	}

	/**
	 * 如果想控制满足条件的集合中元素的个数范围,也可以最大和最小值
	 */
	public void populateSubset(int[] values, int begin, int end,
			int sumInStack, int expectedSum, int minNum, int maxNum) {

		/*
		 * 判断Stack中的数据和是否等于目标值,如果是则输出当前Stack中的数据
		 */
		if (sumInStack == expectedSum) {
			
			/*
			 * 只有当子集中元素个数在期望的范围内[minNum, maxNum],才打印出结果。
			 */
			if (stack.size() >= minNum && stack.size() <= maxNum) {
				print(stack, expectedSum);
			}
		}

		for (int currentIndex = begin; currentIndex < end; currentIndex++) {
			/*
			 * 如果当前Stack中的和加上当前index的数据小于等于目标值, 那么将当前的index的数据添加到Stack中去,
			 * 同时,将当前Stack中所有数据的和加上新添加到Stack中的数值
			 */
			if (sumInStack + values[currentIndex] <= expectedSum) {
				stack.push(values[currentIndex]);
				sumInStack += values[currentIndex];
				// 当前index加上1,递归调用本身
				populateSubset(values, currentIndex + 1, end, sumInStack,
						expectedSum, minNum, maxNum);

				sumInStack -= stack.pop();
			}

		}
	}

	/**
	 * 打印符合条件的子集数据 如:15 = 1+2+4+6+2
	 * 
	 * @param stack
	 * @param expectedSum
	 */
	private void print(Stack<Integer> stack, int expectedSum) {
		sb.setLength(0);
		sb.append(expectedSum + " = ");
		for (int element : stack) {
			sb.append(element + "+");
		}
		System.out.println(sb.deleteCharAt(sb.length() - 1).toString());
	}

	public static void main(String[] args) {

		// 指定数据集
		int[] sourceData = { 1, 2, 3, 4, 5, 6, 2, 7, 8, 9, 10, 11, 13, 14, 15 };

		PopulateSubsetByStack example = new PopulateSubsetByStack();

		/*
		 * 计算并打印出和为15的所有子集
		 */
		System.out.println("计算并打印出和为15的所有子集");
		 example.populateSubset(sourceData, 0, sourceData.length, 0, 15);
		
		 /* 
		 * 计算并打印出和为18的所有子集
		 */
		 System.out.println("计算并打印出和为18的所有子集");
		 example.populateSubset(sourceData, 0, sourceData.length, 0, 18);

		/*
		 * 计算和为15的所有子集,并且子集中的元素个数要至少3个至多5个。
		 */
		 System.out.println("计算和为15的所有子集,并且子集中的元素个数要至少3个至多5个");
		example.populateSubset(sourceData, 0, sourceData.length, 0, 15, 3, 5);
	}
}


结果输出如下:
计算并打印出和为15的所有子集
15 = 1+2+3+4+5
15 = 1+2+3+2+7
15 = 1+2+3+9
15 = 1+2+4+6+2
15 = 1+2+4+8
15 = 1+2+5+7
15 = 1+2+2+10
15 = 1+3+4+5+2
15 = 1+3+4+7
15 = 1+3+5+6
15 = 1+3+2+9
15 = 1+3+11
15 = 1+4+2+8
15 = 1+4+10
15 = 1+5+2+7
15 = 1+5+9
15 = 1+6+8
15 = 1+14
15 = 2+3+4+6
15 = 2+3+2+8
15 = 2+3+10
15 = 2+4+2+7
15 = 2+4+9
15 = 2+5+6+2
15 = 2+5+8
15 = 2+6+7
15 = 2+2+11
15 = 2+13
15 = 3+4+6+2
15 = 3+4+8
15 = 3+5+7
15 = 3+2+10
15 = 4+5+6
15 = 4+2+9
15 = 4+11
15 = 5+2+8
15 = 5+10
15 = 6+2+7
15 = 6+9
15 = 2+13
15 = 7+8
15 = 15
计算并打印出和为18的所有子集
18 = 1+2+3+4+6+2
18 = 1+2+3+4+8
18 = 1+2+3+5+7
18 = 1+2+3+2+10
18 = 1+2+4+5+6
18 = 1+2+4+2+9
18 = 1+2+4+11
18 = 1+2+5+2+8
18 = 1+2+5+10
18 = 1+2+6+2+7
18 = 1+2+6+9
18 = 1+2+2+13
18 = 1+2+7+8
18 = 1+2+15
18 = 1+3+4+2+8
18 = 1+3+4+10
18 = 1+3+5+2+7
18 = 1+3+5+9
18 = 1+3+6+8
18 = 1+3+14
18 = 1+4+5+6+2
18 = 1+4+5+8
18 = 1+4+6+7
18 = 1+4+2+11
18 = 1+4+13
18 = 1+5+2+10
18 = 1+6+2+9
18 = 1+6+11
18 = 1+2+7+8
18 = 1+2+15
18 = 1+7+10
18 = 1+8+9
18 = 2+3+4+2+7
18 = 2+3+4+9
18 = 2+3+5+6+2
18 = 2+3+5+8
18 = 2+3+6+7
18 = 2+3+2+11
18 = 2+3+13
18 = 2+4+5+7
18 = 2+4+2+10
18 = 2+5+2+9
18 = 2+5+11
18 = 2+6+2+8
18 = 2+6+10
18 = 2+2+14
18 = 2+7+9
18 = 3+4+5+6
18 = 3+4+2+9
18 = 3+4+11
18 = 3+5+2+8
18 = 3+5+10
18 = 3+6+2+7
18 = 3+6+9
18 = 3+2+13
18 = 3+7+8
18 = 3+15
18 = 4+5+2+7
18 = 4+5+9
18 = 4+6+8
18 = 4+14
18 = 5+6+7
18 = 5+2+11
18 = 5+13
18 = 6+2+10
18 = 2+7+9
18 = 7+11
18 = 8+10
计算和为15的所有子集,并且子集中的元素个数要至少3个至多5个
15 = 1+2+3+4+5
15 = 1+2+3+2+7
15 = 1+2+3+9
15 = 1+2+4+6+2
15 = 1+2+4+8
15 = 1+2+5+7
15 = 1+2+2+10
15 = 1+3+4+5+2
15 = 1+3+4+7
15 = 1+3+5+6
15 = 1+3+2+9
15 = 1+3+11
15 = 1+4+2+8
15 = 1+4+10
15 = 1+5+2+7
15 = 1+5+9
15 = 1+6+8
15 = 2+3+4+6
15 = 2+3+2+8
15 = 2+3+10
15 = 2+4+2+7
15 = 2+4+9
15 = 2+5+6+2
15 = 2+5+8
15 = 2+6+7
15 = 2+2+11
15 = 3+4+6+2
15 = 3+4+8
15 = 3+5+7
15 = 3+2+10
15 = 4+5+6
15 = 4+2+9
15 = 5+2+8
15 = 6+2+7
0
3
分享到:
评论

相关推荐

    输出集合的所有子集

    在IT领域,尤其是在编程与算法设计中,"输出集合的所有子集"是一个常见的问题,它不仅考验了程序员对数据结构的理解,还涉及到了递归、位运算等多种技术的应用。根据给定的文件信息,我们可以深入探讨两个实现方法:...

    数据集目录,其中 包含子集和问题的示例,其中一组 给出数字,并且希望找到至少一个子集 总和为给定的目标值.rar

    此外,优化是关键,因为原始的子集和问题是NP完全问题,对于大规模数据可能无法在合理时间内得到解决方案。因此,可能会需要考虑近似算法、贪心策略或使用并行计算等手段来提高效率。 总之,这个数据集提供了一个...

    js中数组中相同的元素进行整合并创建一个新数组.pdf

    总之,`sortArr`函数提供了一种高效的方法,它不仅可以对数组中的元素进行排序,还可以通过特定属性将具有相同值的对象合并到一起,生成的新数组更便于后续的数据处理和分析。在实际开发中,这种功能可以应用于各种...

    回溯法求解子集和问题

    这个问题的目标是从给定的一组整数中找出所有可能的子集,使得这些子集的元素和等于一个特定的目标值。在本案例中,我们将深入探讨如何使用回溯法来解决这个经典的问题。 首先,我们需要理解回溯法的基本思想。回溯...

    子集和数 C语言求解

    在编程领域,子集和数问题是一个经典的算法问题,它要求我们从给定的数集中找出所有可能的子集,使得这些子集的元素之和等于一个特定的目标值。在这个问题中,我们使用C语言来解决,同时标签指出了解决这个问题的一...

    子集和问题(算法设计,acm)

    子集和问题(SubSet Sum Problem)是一个经典的计算机科学问题,在算法设计、数据结构、甚至密码学等领域都有广泛的应用。该问题的基本形式是:给定一组整数和一个目标值,判断是否存在该数组的一个子集,其元素之和...

    MATLAB中矩阵与数组的区别,一维数组相当于向量,二维数组相当于矩阵.所以矩阵是数组的子集

    数除以数组k./A和A.\k是每个元素除以k,而数组除法A.\B和B./A是矩阵除法的另一种形式,与矩阵左除和右除相对应。 举例来说,如果A=[1 2;3 4],B=[4 3;2 1],我们可以计算: - r1=100+A,这将得到一个新矩阵,其中每...

    C#构造Json数组

    在现代软件开发过程中,数据交换格式的选择至关重要,JSON(JavaScript Object Notation)作为轻量级的数据交换格式,在Web应用中得到了广泛的应用。在.NET框架下,利用C#语言处理JSON数据变得非常便捷。本文将详细...

    c# 数据组合 从一组数据中 返回组合的和等于某个值 的所有组合

    本主题探讨的是如何从一组数据中找到所有组合,这些组合的和等于给定的目标值。这个问题通常被称为“子集和”或“背包问题”的变种。下面将详细介绍如何实现这个功能。 首先,我们需要理解基本的组合概念。组合是...

    基于MPI+C++的数组求和程序

    在这个程序中,每个进程将读取一部分数据,并计算其和,最后通过通信将局部结果汇总到一个主进程中,从而得到整个数组的总和。 程序的核心部分可能包括以下几个步骤: 1. **初始化**:每个进程通过调用`MPI_Init`...

    子集生成的三种方法.rar

    在IT领域,子集生成是数据结构和算法中常见的问题,尤其在计算机科学的理论研究和实际应用中具有重要意义。本资源"子集生成的三种方法.rar"包含使用C++编程语言实现的三种不同的子集生成算法:回溯法、递归以及动态...

    回溯法求解子集和数给定一个n个整数的集合X={x1,x2....xn}和整数y,找出和等于y的X的子集Y.

    根据给定的信息,本文将详细解释如何利用回溯法解决子集和问题。具体来说,我们将探讨以下几个方面: 1. **子集和问题定义及应用场景**:解释子集和问题的基本概念及其在实际中的应用。 2. **回溯法原理**:介绍...

    perl数组.docx

    Perl中的数组是编程中存储和处理一系列数据的重要工具。数组是一种有序的数据集合,可以容纳不同类型的元素,包括整数、浮点数、字符串甚至其他数组。以下是对Perl数组的详细说明: 1. **列表和数组的基本概念** -...

    子集(二进制序列枚举法)1

    子集(二进制序列枚举法)是一种解决数组子集问题的方法,它涉及到计算机科学中的位操作和组合数学。给定一个互不相同的整数数组 `nums`,任务是生成所有可能的子集,包括空集,并且不包含重复的子集。问题的关键...

    matlab数组字符串的使用

    在 MATLAB 中,字符串数组是一种非常重要的数据类型,它允许我们存储和处理文本数据。下面将详细探讨如何在 MATLAB 中创建、访问、修改和操作字符串数组。 1. **创建字符串数组**: 创建字符串数组时,我们可以...

    数组下标法、分治法求解众数

    在编程和算法设计中,"众数"是一个重要的概念,它指的是在一组数据中出现次数最多的数值。在处理数据统计和分析的问题时,众数能够帮助我们了解数据集中最常见的值。本项目通过"数组下标法"和"分治法"这两种方法来...

    php数组函数序列之array_slice() – 在数组中根据条件取出一段值,并返回

    `array_slice()` 是 PHP 中一个非常实用的数组处理函数,它允许我们从数组中提取一个子数组,根据指定的偏移量(offset)和长度(length)进行截取。这个函数对于处理大型数组或者需要部分数据的情况非常有用。在...

    5二维数组.pdf

    3. 如果广义表的元素全为原子,它可能是线性表,但线性表不一定是广义表的子集,因此这个陈述是错误的。 4. 使用三元组表示稀疏矩阵的非零元素确实可以节省存储空间,所以这个陈述是正确的。 5. 压缩存储稀疏矩阵是...

    设计一个用回溯法搜索子集空间树的函数

    0-1背包问题是一种经典的组合优化问题,给定一组物品,每种物品都有一定的重量和价值,还有一个背包可以承受的最大重量,目标是选择一些物品放入背包中,使得所选物品的总价值最大化。需要注意的是,每种物品只能...

    php递归获取子级,父级,无限极分类,带demo,效率超高

    这个压缩包中的内容显然提供了一个高效的方法来处理这类问题,通过递归算法实现无限级分类,并且附带了示例代码(DataTree.php 和 index.php...正确理解和使用递归算法,可以大大提高处理复杂数据结构的效率和便捷性。

Global site tag (gtag.js) - Google Analytics