【问题标题】:Algorithm to iterate through sample space of numbers迭代数字样本空间的算法
【发布时间】:2011-03-21 11:09:02
【问题描述】:

我希望这不是一个骗局,但很难将问题归结为关键字!

这一直是我想知道的事情。假设您有一个黑匣子,它将 n 个整数作为输入(其中 n > 1)。鉴于整数值有一个界限,你将如何编写一个将整个样本空间推过黑匣子的算法? (如果 n 可以在运行时指定,则加分)

我在 n = 2 时的尝试如下:

int min = 0;
int max = 9;
int a = min;
int b = min;

while(a <= max && b <= max)
{
  blackBox(a, b);
  a++;
  if(a > max)
  {
    a = min;
    b++;
  }
}

上面的代码适用于两个变量,但正如您可能猜到的那样,当 n 接近两位数时,我的算法变得非常丑陋。

除了像我做的那样嵌套 if 语句之外,还有更好的方法吗?

我知道一个不好的方法,那就是为每次迭代随机生成值并保存以前迭代的输入,这样你就不会用相同的变量戳黑盒子两次。但是,我希望有一种更快的方法,因为随着唯一黑盒调用的数量接近 (max - min + 1) ^ n

,碰撞确实会影响执行时间

【问题讨论】:

    标签: algorithm language-agnostic numbers iteration


    【解决方案1】:

    为什么不使用嵌套循环?然后,您只需根据需要添加更多嵌套循环。

    可能不会过于高效,但您确实表明您需要覆盖 整个 样本空间,因此您将不得不运行输入变量值的所有可能组合 - 所以我怀疑在效率方面您可以做很多事情,除非可以仅针对状态空间的一部分进行评估。

    int min = 0;
    int max = 9;
    for( int a = min ; a <= max ; ++a )
        for( int b = min ; b <= max ; ++b )
            blackBox( a , b );
    

    另外,我想你会发现唯一调用的数量是(max - min + 1) ^ n,而不是相反。

    编辑:

    与已经建议的不同的运行时版本

    Imre L 使用与您的问题相同的语言类型(类似于 C)的实时版本似乎一针见血,但既然您已将其标记为语言不可知论者我决定尝试一些不同的东西(另外,我现在正在学习 Python,所以正在寻找练习的借口)。

    这是一个 Python 实时版本,在每种情况下,x 都将是一个 n 元组,例如 [1,0,3,2]。我要说的只是这 not 在状态空间中包含 max(在下面的示例中,它将使用 0 到 2,而不是 3)所以你必须增加 @987654326 @使用前。

    import itertools 
    
    min = 0
    max = 3
    n = 4
    
    for x in itertools.product(range(min,max), repeat=n):
            blackBox( x )
    

    【讨论】:

    • 嵌套循环是个好主意!如果您想在运行时指定要迭代的变量数量,我想我对采用哪种方法很感兴趣。我将重新提出我的问题,稍微反映一下。另外,感谢您的更正,我已经解决了我的问题:)
    【解决方案2】:

    数字将保存在数组a 中,该数组将动态设置,例如:int a[] = new int[n]

    如果blackBox 不能修改为将样本作为数组,那么您可以编写一个丑陋的包装函数来使用不同数量的参数调用它,或者动态执行它几乎不走运。

    (程序)伪代码:

    int min = 0;
    int max = 9;
    int a[] = array();
    int count = length(a);
    
    setToMinValue(a);
    
    while(a[count-1] <= max)
    { 
      blackBox(a); // or bb(a[0],a[1],...)
      a[0]++;
      //while next number needs to be increased
      for (int i = 0; a[i] > max && i < count-1; i++) {
        a[i] = min;
        a[i+1]++;
      }
    }
    

    【讨论】:

      【解决方案3】:

      这是一个通用的 Java 解决方案:

      public class Counter implements Iterator<int[]> {
          private int[] max;
          private int[] vector;
      
          public Counter(int[] maxValues) {
              this.max = maxValues;
              this.vector = new int[maxValues.length];
          }
      
          public int[] next() {
              if (!hasNext())
                  throw new NoSuchElementException();
      
              int[] res = vector.clone();
              int i = 0;
              while (i < vector.length && vector[i] == max[i]) {
                  vector[i] = 0;
                  i++;
              }
              if (i == vector.length)
                  vector = null;
              else
                  vector[i]++;
      
              return res;
          }
      
          @Override
          public boolean hasNext() {      
              return (vector != null);
          }
      
          @Override
          public void remove() {
              throw new UnsupportedOperationException();      
          }
      
          public static void main(String[] args) {
              Counter c = new Counter(new int[]{3});
              while (c.hasNext()) {
                  System.out.println(Arrays.toString(c.next()));
              }
          }
      }
      

      构造函数接收每个位置的最大值。最小值始终为 0(因此您可以使用它来模拟任何基数和任何“混合基数”中的计数器)。我在底部添加了一个使用示例。

      【讨论】:

        【解决方案4】:

        您可以将黑盒的每个输入视为max - min + 1radix 系统中的n 数字。例如,如果min = 3 和max = 12,那么max - min + 1 == 10 和黑盒子的每个输入对应于十进制系统中的n 位数字。只需遍历从0 到(max - min + 1)^n 的所有数字,解码每个数字并将结果向量输入黑盒。

        这是一个 Java 实现:

        public static interface BlackBox {
            void consume(int... vector);
        }
        
        public static void iterateSample(int min, int max, int n, BlackBox bb) {
            int radix = max - min + 1;
            long limit = (long) Math.pow(radix, n);  /* Imprecise for larger numbers! */
            for (int i = 0; i < limit; i++) {
                int encoded = i;
                int[] decoded = new int[n];
                for (int j = 0; j < n; j++) {
                    decoded[j] = min + (encoded % radix);
                    encoded /= radix;
                }
                bb.consume(decoded);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-03-15
          • 1970-01-01
          • 1970-01-01
          • 2013-12-15
          • 2015-03-09
          • 1970-01-01
          • 2012-09-29
          • 2021-11-15
          • 2023-03-04
          相关资源
          最近更新 更多