zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    IOS Charles(代理服务器软件,可以用来拦截网络请求)
    Javascript中addEventListener和attachEvent的区别
    MVC中实现Area几种方法
    Entity Framework Code First 中使用 Fluent API 笔记。
    自定义JsonResult解决 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    An entity object cannot be referenced by multiple instances of IEntityChangeTracker 的解决方案
    Code First :使用Entity. Framework编程(8) ----转发 收藏
    Code First :使用Entity. Framework编程(6) ----转发 收藏
    Code First :使用Entity. Framework编程(5) ----转发 收藏
  • 原文地址:https://www.cnblogs.com/lovesqcc/p/4038357.html
Copyright © 2011-2022 走看看