1 问题描述

求n个正整数构成的一个给定集合A = {a1,a2,a3,…,an}的子集,子集的和要等于一个给定的正整数d。请输出所有符合条件的子集。

2 解决方案

2.1 全排列思想求解

方法1:首先,将子集保存在一个数组链表中,每次往链表中添加一个元素;

从空集增加到最大集,再回溯,递归返回的时候,再将链表最后一个元素从子集移出;

这样就实现了,元素在与不在子集中,这两种状态。

注意,每次加入一个元素得到的,子集数组中的元素就构成了一个子集。

  1. package com.liuzhen.chapter12;
  2. import java.util.ArrayList;
  3. public class SubSet {
  4. public ArrayList<Integer> list = new ArrayList<Integer>(); //用于存放求取子集中的元素
  5. //求取数组链表中元素和
  6. public int getSum(ArrayList<Integer> list) {
  7. int sum = 0;
  8. for(int i = 0;i < list.size();i++)
  9. sum += list.get(i);
  10. return sum;
  11. }
  12. /*
  13. * 参数step:选中数组A中第step个元素为子集元素
  14. * 函数功能:求取数组A中一个子集元素,其相加之和等于m
  15. */
  16. public void getSubSet(int[] A, int m, int step) {
  17. while(step < A.length) {
  18. list.add(A[step]); //递归执行语句,向数组链表中添加一个元素
  19. if(getSum(list) == m) //链表中元素和等于m
  20. System.out.println(list);
  21. step++;
  22. getSubSet(A, m, step);
  23. list.remove(list.size() - 1); //回溯执行语句,删除数组链表最后一个元素
  24. }
  25. }
  26. public static void main(String[] args) {
  27. SubSet test = new SubSet();
  28. int[] A = new int[6];
  29. for(int i = 0;i < 6;i++) {
  30. A[i] = i + 1;
  31. }
  32. test.getSubSet(A, 8, 0);
  33. }
  34. }

运行结果:

  1. [1, 2, 5]
  2. [1, 3, 4]
  3. [2, 6]
  4. [3, 5]

2.2 状态空间树思想求解

方法2:从元素在与不在子集这两种状态来考虑,因为每个元素都有两种状态,

可以理解为一种二叉树的形式,如下图:

每一个元素带有一个属性,在不在子集中,1(true)表示在子集,0(false)表示不再自己中。

每个元素的状态初始化为1,实际上无需去构造二叉树。

第一个递归将所有元素逐个放入子集,当所有元素放入子集后回溯。

第一次递归返回后,将最后一个元素移出子集,这样每个元素在与不在子集的状态都可以遍历到,每次遍历到最后一个元素时,按照元素的状态打印字符序列,得到的就是一个子集。

  1. package com.liuzhen.chapter12;
  2. import java.util.ArrayList;
  3. public class SubSet {
  4. public int getSum1(boolean[] visited, int[] A) {
  5. int sum = 0;
  6. for(int i = 0;i < A.length;i++) {
  7. if(visited[i])
  8. sum += A[i];
  9. }
  10. return sum;
  11. }
  12. public void getSubSet1(boolean[] visited, int[] A, int m, int step) {
  13. if(step == A.length) {
  14. if(getSum1(visited, A) == m) {
  15. for(int i = 0;i < A.length;i++) {
  16. if(visited[i])
  17. System.out.print(A[i]+" ");
  18. }
  19. System.out.println();
  20. }
  21. return;
  22. }
  23. visited[step] = true;
  24. getSubSet1(visited, A, m, step + 1);
  25. visited[step] = false;
  26. getSubSet1(visited, A, m, step + 1);
  27. }
  28. public static void main(String[] args) {
  29. SubSet test = new SubSet();
  30. int[] A = new int[6];
  31. boolean[] visited = new boolean[6];
  32. for(int i = 0;i < 6;i++) {
  33. A[i] = i + 1;
  34. visited[i] = false;
  35. }
  36. test.getSubSet1(visited, A, 8, 0);
  37. }
  38. }

运行结果:

  1. 1 2 5
  2. 1 3 4
  3. 2 6
  4. 3 5

java实现子集和问题的更多相关文章

  1. JAVA语言学校的危险性

    Java语言学校的危险性(译文) 作者: 阮一峰 日期: 2008年12月 7日 下面的文章是More Joel on Software一书的第8篇. 我觉得翻译难度很大,整整两个工作日,每天8小时以 ...

  2. [No0000184]JAVA语言学校的危险性

    下面的文章是More Joel on Software一书的第8篇. 原文: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools ...

  3. JavaEE填空与判断

    Java EE软件工程师认证考试 试题库- 填空题和选择题   一.     填空题 1. HTML网页文件的标记是__html__,网页文件的主体标记是_body__,标记页面标题的标记是__tit ...

  4. Project Euler 106:Special subset sums: meta-testing 特殊的子集和:元检验

    Special subset sums: meta-testing Let S(A) represent the sum of elements in set A of size n. We shal ...

  5. JavaScript: 世界上最被误解的语言|Douglas Crockford

    JavaScript: 世界上最被误解的语言 JavaScript: The Wrrrld's Most Misunderstood Programming Language Douglas Croc ...

  6. JS 精粹(一)

    先说说JS是容易被误解的语言的观点.从名字上来看,"Java"这似乎暗示着这门语言与Java的关系:好像这门语言是Java的子集,或比Java弱.但实际与Java并无关系,如果说非 ...

  7. 一篇博文将JavaScript尽收眼底

    简介 这篇文章是为专业程序员介绍的JavaScript语言的,它是一种小巧的语言,如果你熟悉其他的编程语言,那么这篇文章对你来讲不是那么难以理解. JavaScript不是Java,他们是两门完全不同 ...

  8. PL真有意思(一):引言

    前言 断断续续学编译原理到之前发过写一个编译器和正则表达式引擎系列文章也有一段时间了,然后最近看完PLP这本书,这本书应该算是入门书,但是对我这种半吊子收获很大.所以为了弥补最近学操作系统和接外包摸的 ...

  9. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

随机推荐

  1. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  2. Cannot parse "1986-05-04": Illegal instant due to time zone offset transition (Asia/Shanghai)

    调查系统错误时,发现了一个很奇怪的现象,出生日期1986-05-04号的用户始终无法注册.发现后台使用使用jodatime的代码demo如下: public static DateTime parse ...

  3. java ->基本数据类型与包装类的概述和转化

    基本类型 包装类概述 在实际程序使用中,程序界面上用户输入的数据都是以字符串类型进行存储的.而程序开发中,我们需要把字符串数据,根据需求转换成指定的基本数据类型,如年龄需要转换成int类型,考试成绩需 ...

  4. 6、保持会话(save)

    前言 为什么要保存会话呢?举个很简单的场景,你在上海测试某个功能接口的时候,发现了一个BUG,而开发这个接口的开发人员是北京的一家合作公司.你这时候给对方开发提bug, 如何显得专业一点,能让对方心服 ...

  5. .NetCore对接各大财务软件凭证API——用友系列(1)

    一.前言 今天,我们转战用友系列的第一个产品---T+/Tplus.前两篇文章讲解分享的都是金蝶的产品,因为本身公司牵涉的业务有限,后续有金蝶其他产品的API对接业务时,会继续来分享经验. T+的AP ...

  6. 09-Python之路---函数进阶

    Python之路---函数进阶️ 程序员三大美德: 懒惰 因为一直致力于减少工作的总工作量. 缺乏耐性 因为一旦让你去做本该计算机完成的事,你将会怒不可遏. 傲慢 因为被荣誉感冲晕头的你会把程序写得让 ...

  7. 基于java的雷电游戏

    基于java的雷电游戏基本功能包括:敌方飞机随机飞行.我方飞机手动控制飞行,射击比拼,游戏闯关等.本系统结构如下: (1)雷电游戏状态调整功能: 在游戏启动时,游戏会自动进行初始化的验证. 若初始化成 ...

  8. java导入web项目httpservlet报错

    于是开始了,调错之路. 解决方法:鼠标右击项目工程——>Build Path——>点击comfigure Build Path进入----->选择java Bulid Path--- ...

  9. 调用 start_kernel

    步骤 1 关闭中断.进入 SVC 模式 ENTRY(stext) THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. THUMB( ...

  10. Python之Flask框架一

    flask是一个使用 Python 编写的轻量级 Web 应用框架.轻巧页就意味着他比较简洁,不过见到的MTV框架还是有的,(MVC)但是最重要的还是他的可扩展性很强,对比与Django框架呢,他的灵 ...