生成真值组合【Java实现】

/**
 * 问题描述: 给定 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

时间: 2024-11-02 23:21:48

生成真值组合【Java实现】的相关文章

【Android】Android Layout Binder——根据layout布局文件自动生成findViewById的java代码的神器

Android Layout Binder是一个网站,能够在线的根据layout布局文件自动生成findViewById的java代码. 网址是http://android.lineten.net/layout.php 如图:

转载——Java与WCF交互(一)补充:用WSImport生成WSDL的Java客户端代码

在<Java与WCF交互(一):Java客户端调用WCF服务>一文中,我描述了用axis2的一个Eclipse控件生成WCF的Java客户端代理类,后来有朋友建议用Xfire.CXF,一直没有尝试,今天有朋友指出JDK6可以用java自带的一个WSImport工具,试了下,果然很爽,这是一个exe文件,位于%JAVA_HOME%\bin下,它的官方使用说明,见:http://download-llnw.oracle.com/javase/6/docs/technotes/tools/share

利用在线工具根据JSon数据自动生成对应的Java实体类

如果你希望根据JSon数据自动生成对应的Java实体类,并且希望能进行变量的重命名,那么“JSON To Java”一定适合你.(下面的地址需要FQ) https://jsontojava.appspot.com/ 简单快速有效,适合追求效率的你.

如何在IJ中使用Jaxb2通过xml定义生成对应的Java Entity类的文件

#0. 准备要转换的xml文件,在Project视界中,右击这个xml文件,在弹出的菜单上选择“Generate XSD schema from XML File...”, 按默认设置生成xsd文件.将xsd 文件移至#1配置段的configuration/sources/source指定的路径下. #1. 打开pom.xml, 加入下面的配置段.其中configuration节点中的内容依具体的项目不同而有不同的设定.一般而言,有3处设定:packageName,outputDirectory

Java采用JNI调用VC++生成的dll(Java与C++交互)

应项目需求,需要android调用java,java再调用C++实现android一个图片匹配的功能,我们作为java组需要和C++和Android进行交互.下面是java和C++采用JNI的方式进行接口传参交互,我做的一个demo并运行成功. 什么是JNI? JNI全拼是Java Native Interface,中文意思为Java本地调用.JNI标准是Java平台的一部分,它允许java和其他语言的代码进行交互.JNI开始是为了本地已经编译好的语言,尤其是C和C++而设计的,我们也可以使用J

Android 网络请求json数据,解析json数据,生成对应的java bean类一步到位,快速开发

Android 网络请求一般都涉及到图片和JSON数据,怎样快速的请求网络JSON数据,解析JSON数据,并且一步生成自己想要的Java bean实体类?这个涉及到Android 开发效率的问题.由于接触Android 网络这方面比较多,自然就找到一些好的方法来快速开发Android 网络模块的相关内容,接下来就为大家揭晓 一步快速请求,解析JSON 数据生成对应的Java bean实体类的方法. 注:我们先把思路讲解下吧: 1.网络请求JSON数据代码可以自己写,当然我还是推荐使用网络上开源的

java高仿新浪微博短链接地址生成工具ShortUrlGenerator.java

原文:仿新浪微博 短链接地址生成工具 ShortUrlGenerator.java 源代码下载地址:http://www.zuidaima.com/share/1550463378934784.htm 仿新浪微博 短链接地址生成工具 ShortUrlGenerator.java String sLongUrl = "http://www.zuidaima.com/share/1550463378934784.htm"; // 3BD768E58042156E54626860E241E9

Axis2发布webservice(3)--axis2生成wsdl文件,并利用wsdl文件来生成WebService的Java代码

一.利用axis2生成wsdl文件 1.file->New->Other->Axis2 Code Generator 2.选择第2个,点击next 3,先点击add folder->浏览选择WebService项目下的bin文件夹,然后在fully Qualified Class name中填入类路径(包括包名) 然后点击Test 测试是否正确. 点击Next 4.可以看到即将发布的WebService名称和命名空间 5.继续Next,选择wsdl文件保存目录 这样services

二维码生成工具类java版

注意:这里我不提供所需jar包的路径,我会把所有引用的jar包显示出来,大家自行Google package com.net.util; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Shape; import java.awt.geom.RoundRectangle2D; import java.a