/**

*问题描述:给定 n个布尔变量,打印所有真值组合。

*例如, n = 2所有真值组合为 (true, false),(true, true),(false, true),(false, false).

*

*算法的基本思路:

*使用一个长度为 n的数组存储着 n个布尔变量;位 1表示 true , 0表示 false,

*生成每一个真值元组,实际上是生成一个由 0 1表示的数组。

*

*生成每一个真值元组的方法:从零开始,逐次加一。

*比如000 -> 001 -> 010 -> 011 -> 100 -> 101 -> 110 -> 111

*

*具体算法:

*每次都从最低位开始,将最低位作【置一】处理

*如果最低位是 0则置 1即可【不进位】;

*如果最低位为 1则置 0由于有进位,进一步将次低位作【置一】处理。

*直至某一位由 0 1为止【不进位】。

*

*例如: 011 :

*最低位为1 0并进位;

*次低位为1 0并进位;

*次次低位为 0 1结果为 100

*

*

*技巧:

*由于这里只涉及置 1 0实际上就是置 true false

*因此,可以直接在数组里存储布尔值,并不必要在 1,0 true, false之间转换。

*

*设置一个结束标识变量 endflag,当 1..1 -> 0..0设置为 true

*

*/

package algorithm;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

public class Combination {

private boolean[] combination ;

private long count;

private boolean endflag;

public Combination(int n) {

if (n <= 0)

throw new IllegalArgumentException("参数必须为正整数");

if (combination == null) {

combination = new boolean[n];

count = 0;

endflag = false;

}

}

/**

* 求解问题,打印所有的真值组合结果。

*

*/

public void solution()

{

System.out.println("n = " + combination.length + " ***** 所有真值组合: ");

do {

System.out.println(getOneTuple());

count++;

increOne();

} while(!terminate());

System.out.println("真值组合数: " + count);

}

/**

* 逐次加一,生成每一个真值元组

*

*/

private void increOne()

{

int i;

for (i=0; i < combination.length; i++) {

// 若为 0,则置 1结束。

if (combination[i] == false) {

combination[i] = true;

break;

}

else {

// 若为 1则置 0并通过 i++转至次低位进行相同处理

combination[i] = false;

}

}

// 1..1 -> 0..0,设置 endflag = true;

if (i == combination.length) { endflag = true; }

}

/**

* 根据整数数组表示生成的真值元组,转化为布尔数组表示生成的真值元组。

*

*/

private String getOneTuple()

{

StringBuilder tuple = new StringBuilder("(");

for (int i=0; i < combination.length; i++) {

tuple.append(combination[i]);

tuple.append(",");

}

// 删除多余的逗号

tuple.deleteCharAt(tuple.length()-1);

tuple.append(")");

return tuple.toString();

}

/**

* 终止条件:结束标识符 endflag = true;

*

*/

private boolean terminate()

{

return endflag == true;

}

public static void main(String[] args) {

BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));

try {

String s = null;

while ((s = stdin.readLine()).matches("[1-9][0-9]*")) {

int n = Integer.parseInt(s);

System.out.println("n = " + n);

Combination c = new Combination(n);

c.solution();

}

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

System.out.println(e.getMessage());

e.printStackTrace();

}

//Combination c = new Combination(3);

// c.solution();

}

}

算法分析:

总的运行时间由两部分组成:置一处理时间 判断结束时间。

T(n) = setBit(n) + judgeEnd(n)

其中: judgeEnd(n) = 2^n,因为从 0..0 -> 1..1 -> 0..0每次变换做一个简单的比较操作,endflag == true,总共花时 2^n

下面计算 setBit(n) :

n = 1 0 -> 1setBit(1) = 1;

n = 2 00-> 01 -> 10 -> 11setBit(2) = 121 【置位次数:1+2+1

n = 3 000 –> 001 -> 010 -> 011 -> 100 -> 101 -> 110 -> 111setBit(3) = 1213121

n = 4 0000 -> 0001 -> 0010 -> 0011 -> 0100 -> 0101 -> 0110 -> 0111 -> 1000 -> 1001 -> .. -> 1111 setBit(4) = 121312141213121

归纳可得:

setBit(n) = n + 2setBit(n-1)setBit(1) = 1 解得: setBit(n) = O(n^2)

T(n) = 2^n

更多相关文章

  1. 字体图标的引入和通过媒体查询改变导航样式
  2. HTML样式和常用选择器
  3. 字体图标的引用和自定义样式/媒体查询的使用
  4. 数据库的CURD操作、PDO本质与原理的学习
  5. CSS之伪类选择器和简单盒子简单案例
  6. 伪类选择器与盒模型常用属性
  7. 伪类选择器-结构伪类、根据位置选择匹配
  8. 7.4——常用标签与应用场景之表格与单元格
  9. css伪类选择器和盒模型

随机推荐

  1. [置顶] pt-table-checksum数据一
  2. [置顶] MYSQL高级命令
  3. Ubuntu编译安装nginx,php,mysql
  4. 使用 Xtrabackup 在线对MySQL做主从复制
  5. 阿里云服务器忘记mysql的登录密码时候如
  6. 如何从MySQL DBs的不同表中提取create语
  7. 装机建项目vs2017和mysql5.7下建项目用EF
  8. 是一个mysql临时表,每个用户访问创建它的
  9. MySQL 一对多查询
  10. 中文乱码问题