5

整数を入力として受け取り、その整数までの数値の可能なすべての順列を出力する関数をJavaで記述したいと思います。例えば:

f(1)

0

f(2)は次を出力する必要があります。

00 01 10 11

f(3)は次を出力する必要があります。

000 001 002 010 011 012 020 021 022 100 .... 220 221 222 ..

つまり、0、1、2の数字の27の順列すべてを出力する必要があります。

f(4)は0000 0001 0002 0003 0010 ... 3330 333133323333を出力する必要があります

f(5)は00000 00001 ...4444344444を出力する必要があります

私はこの問題を解決しようとしてきましたが、それを行う方法を理解できず、必要なループの数に混乱し続けるようです。誰かがこの問題を解決する方法を知っていますか?前もって感謝します。

4

1 に答える 1

3

数えて変換するだけです。私はここで以前の答えに役立つはずの何かを書きました。

これは比較的簡単に解決できる問題です。

基本的に、 Σ= {0、1、2}である文字列 Σ^5のセットを計算しているだけです。

static Iterable<String> strings(final int radix, final int digits) {
  return new Iterable<String>() {

    public Iterator<String> iterator() {
      return new Iterator<String>() {

        private final String pad;
        {
          final StringBuilder buf = new StringBuilder(digits);
          for (int n = digits; n >= 0; --n) {
            buf.append('0');
          }
          pad = buf.toString();
        }

        private final int hi = (int) Math.pow(radix, digits);
        private int cursor;

        public boolean hasNext() {
          return cursor < hi;
        }

        public String next() {
          final String rsl = Integer.toString(cursor++, radix);
          return pad.substring(0, digits - rsl.length()) + rsl;
        }

        public void remove() {
          throw new UnsupportedOperationException();
        }
      };
    }
  };
}

...次のように使用できます。

for (final String val : strings(3, 5)) {
  System.out.println(val);
}

基本的に、[0、3 ^ 5)の間隔で数値を生成します。ここで、3は基数、5は目的の文字列の長さであり、数値を3部形式に変換します。000000になり、3^5100000になります。また、大きすぎる基数を使用しないように注意する必要があります。そうしないと、結果Stringに不良文字が含まれることになります。


ここでの解決策は、単にを呼び出すことstrings(n, n)です。基数または必要な桁の長さによっては、代わりにlongまたはを使用することもできBigIntegerます。

また、に依存しているInteger.toStringため、次の注意事項を忘れないでください...

基数が。より小さいCharacter.MIN_RADIXか大きい場合Character.MAX_RADIXは、代わりに基数10が使用されます。

Character.MIN_RADIXis2MAX_RADIXisの値を確認できます36。この範囲外の基数を使用すると、デフォルトで10...になります。数字用のカスタム拡張文字セットを使用して独自の変換を作成する必要があります。このような関数の一般的な形式はitoa次のとおりです。

    private static final char[] ALPHABET = { '0', '1', '2', '3', ... };

    public static String itoa(int value, final int radix, int width) {
      final char[] buf = new char[width];
      while (width > 0) {
        buf[--width] = ALPHABET[value % radix];
        value /= radix;
      }
      return new String(buf);
    }

以下は、使用法の実際の例です(ideoneの結果を参照してください)。

static Iterable<String> f(final int n) {
  return strings(n, n);
}

public static void main(final String[] argv) {
  for (int n = 1; n <= 5; ++n) {
    for (final String string : f(n)) {
      System.out.printf("%s ", string);
    }
    System.out.println();
  }
}

...これは以下を生成します:

0

00 01 10 11

000 001 002 010 011 012 020 021 022100101102110111..。

0000 0001 0002 0003 0010 0011 0012 0013 0020 0021 0022 00230030..。

00000 00001 00002 00003 00004 00010 00011 00012 00013 00014 00020 0002100022..。

于 2012-09-12T21:37:03.293 に答える