摘要: 使用位图生成真值组合。
难度: 初级。
 
/**
* 问题描述: 给定 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. Kafka中Producer端封装自定义消息

    我们知道KeywordMessage就是被kafka发送和存储的对象.所以只需要模拟出这个就可以发送自定义消息了. 比如我需要将用户的id,user,age,address和访问ip和访问date记录 ...

  2. ubuntu的安装方法

    Ubuntu 是一个启动速度超快.界面友好.安全性好的开源操作系统,它由全球顶尖开源软件专家开发,适用于桌面电脑.笔记本电脑.服务器以及上网本等,并且它可以永久免费使用.如果你厌倦了Windows,如 ...

  3. 多线程的学习与GDI的学习

    今天又是一周的周五,感觉过的好快,我感觉不是期盼周末的到来,而是感觉现在已经习惯啦每天坐在这里敲代码,其实我是一个性格非常开朗的女生,现在不知道为什么感觉默默地坐在自己位置上面敲代码成为了我习以为常的 ...

  4. MYSQL系列之(二)

    上一篇文章讲的是mysql的基本操作,这一篇会有一点难以理解,本节主要内容mysql视图,存储过程,函数,事务,触发器,以及动态执行sql 视图view 视图是一个虚拟表,其内容由查询定义.同真实的表 ...

  5. 【LeetCode】Pascal's Triangle II (杨辉三角)

    Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3 ...

  6. java框架---->zxing框架的使用

    今天我们就来学习一下zxing的用法,这里只涉及到java se的部分. zxing的学习 如果在java se环境中使用zxing,需要在maven的pom.xml中添加依赖: <depend ...

  7. 手机QQ会员H5加速方案——sonic技术内幕

    版权声明:本文由况鹰原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/141 来源:腾云阁 https://www.qclou ...

  8. POJ 3461 Oulipo[附KMP算法详细流程讲解]

      E - Oulipo Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit ...

  9. linux的~和/的区别

    转自:https://zhidao.baidu.com/question/166486946.html /是目录层的分隔.表示符.只有一个/表明是root,/etc/表明是根目录下面的etc目录(当然 ...

  10. 阿里云 elastic search 重启 过程

    阿里云 es 重启 elasticsearch  重启 过程 实例变更中   53.13%   准备ECS资源 已完成节点数:4/4, 进度:100%     准备容器服务 进度:100%     变 ...