【问题标题】:Refactor for loops into function将 for 循环重构为函数
【发布时间】:2009-04-06 10:03:02
【问题描述】:

我有这段java代码:

int maxDigit = 4;
for(int a = 0; a <= maxDigit; a++)
{
  for(int b = 0; b <= maxDigit; b++)
  {
    if(b != a){
      for(int c = 0; c <= maxDigit; c++)
      {
        if(c != a && c != b)
        {
          for(int d = 0; d <= maxDigit; d++)
          {
            if(d != a && d != b && d != c)
            {
              for(int e = 0; e <= maxDigit; e++)
              {
                if(e != a && e != b && e != c && e != d)
                {
                  String temp = a + "" + b + "" + c + "" + d + "" + e;
                  System.out.println(temp);
                  permutations.add(Integer.parseInt(temp));
                }
              }
            }
          }
        }
      }
    }
  }
}

如何将这段代码转化为函数?

目的是生成数字 0 到 9 的排列,在上面的代码中,它是从 0 到 4。将它放入函数中似乎很容易,但我无法立即找到它。

【问题讨论】:

  • 这不能回答您的问题,但是...通过连接字符串然后解析结果来创建整数?这是我能想到的效率最低的方法。改用“permutations.add(a*10000 + b*1000 + c*100 + d*10 + e)”。

标签: java function for-loop


【解决方案1】:

这是获取all permutations of a string 的经典问题的变体。

你的教授希望你做出的归纳是这个问题很适合使用递归的解决方案。

字符串s排列的基本算法如下:

  1. 选择s中的第一项。
  2. 获取s 中其他项目的所有排列(所选项目除外)。
  3. 将所选项目添加到步骤 2 中的每个排列。
  4. 重复s 的下一个字符。

这是使用Functional Java 库的有效解决方案。

导入这些...

import fj.F;
import fj.P2;
import fj.P1;
import fj.data.Stream;
import static fj.data.Stream.nil;
import static fj.data.Stream.cons;
import static fj.data.Stream.range;
import static fj.data.Enumerator.charEnumerator;
import static fj.data.Show.streamShow;
import static fj.data.Show.charShow;
import static fj.P2.map2_;

寻找排列的递归函数:

public Stream<Stream<Character>> permutations(final Stream<Character> s) {
  return selections(s).bind(
    new F<P2<Character, Stream<Character>>, Stream<Stream<Character>>>() {
      public Stream<Stream<Character>>()
        f(final P2<Character, Stream<Character>> ys) {
          return permutations(ys._2()).bind(cons(ys._1()));
        }
      });
}

依次选择每个元素的递归函数:

public Stream<P2<Character, Stream<Character>>>
selections(final Stream<Character> s) {
  if (xs.isEmpty())
    return nil();
  else {
    final char x = xs.head();
    final Stream<Character> xs = s.tail()._1();
    return cons(P.p(x, xs),
      new P1<Stream<P2<Character, Stream<Character>>>>() {
        public Stream<P2<Character, Stream<Character>>> _1() { 
          return selections(xs).map(map2_().f(cons(x))));
        }
      });
  }
}

然后,获取字符“0”到“9”的所有排列:

Show<Stream<Character>> s = streamShow(charShow);
for (Stream<Character> ps : permutations(range(charEnumerator, '0', '9'))) {
  System.out.println(s.showS(ps));
}

编辑:这实际上是comonads 的一个很好的用例。使用最新的函数式 Java 主干头,您可以使用 Zipper comonad 执行此操作,如下所示:

public static Stream<Stream<Character>> perms(Stream<Character> s) {
  Stream<Stream<Character>> r = single(Stream.<Character>nil());
  for (final Zipper<Character> z : fromStream(s))
    r = join(z.cobind(
      new F<Zipper<Character>, Stream<Stream<Character>>>() {
        public Stream<Stream<Character>> f(final Zipper<Character> zp) {
          return perms(zp.lefts().reverse().append(zp.rights())).map(compose(
            Stream.<Character>cons().f(zp.focus()),
              P.<Stream<Character>>p1()));
        }
      }).toStream());
  return r;
}

【讨论】:

  • 看起来Functional Java真的可以使用类型推断......我很难看到所有,Stream>下的实际操作。
【解决方案2】:

填补漏洞:

int[] indexes = { 0, 0, 0, 0, 0 };
addPermutations(maxDigit, indexes, 0, permutations);


void addPermutations(int max, int[] indexes, int currentIndex, List<Integer> permutations) {
    if (currentIndex == indexes.length) {
        // terminal case
        String temp = ...;
        System.out.println(temp);
        permutations.add(Integer.parseInt(temp));
    } else {
        // recursive case
        for (int i = 0; i <= max; i++) {
            if (... != i) {
                indexes[currentIndex] = i;
                addPermutations(max, indexes, currentIndex+1, permutations);
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    没有代码,但算法应该如下。

    假设您想要从 0 到 7 的 5 位数字的所有排列。要做到这一点:

    • 计算j = 100000 的基数为 7 的十进制值(1 + 5 个零)
    • 循环 for i = 0; i &lt; j; ++i,将每个 i 转换为 base-7 系统,可以选择在前面添加零。

    【讨论】:

      【解决方案4】:

      您可以使用 N 叉树,每个点有 4 个分支,递归地导航树并越过已经看到该节点数字的分支?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-03
        • 1970-01-01
        • 1970-01-01
        • 2018-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多