摘要: 使用位图生成真值组合。
难度: 初级。
 
/**
* 问题描述: 给定 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 -> 1   setBit(1) = 1;

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

n = 3 时 000 –> 001 -> 010 -> 011 -> 100 -> 101 -> 110 -> 111 setBit(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

Java实现使用位图生成真值组合的更多相关文章

  1. java二维码生成-谷歌(Google.zxing)开源二维码生成学习及实例

    java二维码生成-谷歌(Google.zxing)开源二维码生成的实例及介绍   我们使用比特矩阵(位矩阵)的QR码编码在缓冲图片上画出二维码 实例有以下一个传入参数 OutputStream ou ...

  2. JAVA WEB项目中生成验证码及验证实例(附源码及目录结构)

    [我是一个初学者,自己总结和网上搜索资料,代码是自己敲了一遍,亲测有效,现将所有的目录结构和代码贴出来分享给像我一样的初学者] 作用 验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计 ...

  3. 疯狂位图之——位图生成12GB无重复随机乱序大整数集

    上一篇讲述了用位图实现无重复数据的排序,排序算法一下就写好了,想弄个大点数据测试一下,因为小数据在内存中快排已经很快. 一.生成的数据集要求 1.数据为0--2147483647(2^31-1)范围内 ...

  4. Verilog-FPGA硬件电路设计之一——if语句优先级(always块中的阻塞赋值生成的组合逻辑电路是按照顺利执行的)

    出处:http://bbs.ednchina.com/BLOG_ARTICLE_3013262.HTM 综合软件:Quartus II 一.有优先级的if语句 if..else if.. else i ...

  5. java自带uuid生成

    java自带uuid生成UUID.randomUUID().toString()

  6. 【java】Freemarker 动态生成word(带图片表格)

    1.添加freemarker.jar 到java项目. 2.新建word文档. 3.将文档另存为xml 格式. 4.将xml格式化后打开编辑(最好用notepad,有格式),找到需要替换的内容,将内容 ...

  7. 如何获取java运行时动态生成的class文件?

    查看运行时生成的文件,以更清楚运行情况. 查看动态生成的类,一般有两个方法: 1. 使用据说是jdk自带包sa-jdi.jar里的工具. 其中,不想自己搞,当然就利用下,sa-jdi.jar 里自带的 ...

  8. Java二维码生成与解码

      基于google zxing 的Java二维码生成与解码   一.添加Maven依赖(解码时需要上传二维码图片,所以需要依赖文件上传包) <!-- google二维码工具 --> &l ...

  9. java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串

    java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串 package com.zdz.test; im ...

随机推荐

  1. beginUpdates和endUpdates-实现UITableView的动画块

    我们在做UITableView的修改,删除,选择时,需要对UITableView进行一系列的动作操作. 这样,我们就会用到 [tableView beginUpdates]; if (newCount ...

  2. PyQt4预定义对话框

    PyQt4中的对话框 对话窗口和对话框是现代GUI应用程序必不可少的一部分.生活中“对话”被定义为发生在两人或更多人之间的会话.而在计算机世界,“对话”则时人与应用程序之间的“会话”.人及对话的形式有 ...

  3. poj_3580 伸展树

    自己伸展树做的第一个题 poj 3580 supermemo. 题目大意 对一个数组进行维护,包含如下几个操作: ADD x, y, d 在 A[x]--A[y] 中的每个数都增加d REVERSE ...

  4. MQTT-SN协议乱翻之实现要点

    前言 本篇是MQTT-SN 1.2协议最后一篇翻译了,主要涉及实现要点,很简短. 需要支持QoS 值为 -1 QoS虽默认设置有0,1,2三个值,但还有一种情况其值为-1.来自客户端的PUBLISH消 ...

  5. Ubuntu 14.04.02 安装openvswitch-2.3.1

    Open vSwitch安装 安装好操作系统 # lsb_release -a LSB Version: core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:c ...

  6. css选择器的性能

    性能排序: 1.id选择器(#myid) 2.类选择器(.myclassname) 3.标签选择器(div,h1,p) 4.相邻选择器(h1+p) 5.子选择器(ul < li) 6.后代选择器 ...

  7. webpack打包jquery并引用

    一,引入webpack插件 //打包第三方 const CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlug ...

  8. PHP获取POST的原始数据的方法

    一般我们都用$_POST或$_REQUEST两个预定义变量来接收POST提交的数据.但如果提交的数据没有变量名,而是直接的字符串,则需要使用其他的方式来接收. 方法一: 使用全局变量$GLOBALS[ ...

  9. DGbroker故障切换示例

    1.主库故障 SQL> startup ORACLE instance started. Total System Global Area bytes Fixed Size bytes Vari ...

  10. 二进制状态压缩dp(旅行商TSP)POJ3311

    http://poj.org/problem?id=3311 Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Subm ...