【问题标题】:Possible paths of NxN array traversing from (0, 0) to (N, N) in a positive direction only?仅在正方向上从 (0, 0) 到 (N, N) 遍历的 NxN 数组的可能路径?
【发布时间】:2017-04-21 02:12:14
【问题描述】:

我们有一个 NxN 数组。我已经找到了仅在正方向上找出从 (0,0) 到 (N,N) 的可能路径数的解决方案。您不能沿对角线向后移动。

解决办法是:

private void matrixProblem(int N) {
    System.out.println("Total count is : " + String.valueOf(path((N-1), (N-1))));
}

private int path(int x, int y) {

    System.out.println("x = " + x + " " + "y = " + y);
    if (x < 0 || y < 0) {
        return 0;
    }
    if (x == 0 && y == 0) {
        return 1;
    }

    return path(x - 1, y) + path(x, y - 1);
}

但是我也想打印所有可能的路径。
就像 3x3 阵列一样,一种可能的路径是:
(0,0) --> (1,0) --> (2,0) --> (2,1) --> (2,2)

3x3 阵列有 6 种可能的路径。这是一个例子。

请为此建议最好的方法。

【问题讨论】:

    标签: java algorithm


    【解决方案1】:

    为了打印所有路径,您需要传递您的历史记录。这意味着:

    • 在每一点,添加当前条目,
    • 递归调用您的函数,
    • 再次删除最后一个条目。

    你也可以

    • 在每一点,复制迄今为止的历史,
    • 将当前条目添加到副本中,
    • 使用副本递归调用您的函数,

    但前者占用的内存和时间更少。这有效:

    import java.util.ArrayList;
    
    public final class MatrixProblem {
    
      private final int mx;
      private final int my;
    
      public MatrixProblem(int N) {
        mx = N;
        my = N;
      }
    
      public int countAndPrint() {
        return numPathsTracing(0, 0, new ArrayList<>());
      }
    
      private int numPathsTracing(int x, int y, ArrayList<String> path) {
        if(x > mx || y > my)
          return 0;
        else if(x == mx && y == my) {
          StringBuilder pathString = new StringBuilder();
          for(String previous : path) {
            pathString.append(previous);
            pathString.append(" -> ");
          }
          pathString.append(pathElement(x, y));
          System.out.println(pathString);
          return 1;
        } else {
          path.add(pathElement(x, y));
          int ret = numPathsTracing(x+1, y, path) + numPathsTracing(x, y+1, path);
          path.remove(path.size() - 1);
          return ret;
        }
      }
    
      private static String pathElement(int x, int y) {
        return "(" + x + ", " + y + ")";
      }
    }
    

    调用为:

    int nPaths = new MatrixProblem(3).countAndPrint();
    System.out.println("Total count is : " + nPaths);
    

    输出:

    (0, 0) -> (1, 0) -> (2, 0) -> (3, 0) -> (3, 1) -> (3, 2) -> (3, 3)
    (0, 0) -> (1, 0) -> (2, 0) -> (2, 1) -> (3, 1) -> (3, 2) -> (3, 3)
    (0, 0) -> (1, 0) -> (2, 0) -> (2, 1) -> (2, 2) -> (3, 2) -> (3, 3)
    (0, 0) -> (1, 0) -> (2, 0) -> (2, 1) -> (2, 2) -> (2, 3) -> (3, 3)
    (0, 0) -> (1, 0) -> (1, 1) -> (2, 1) -> (3, 1) -> (3, 2) -> (3, 3)
    (0, 0) -> (1, 0) -> (1, 1) -> (2, 1) -> (2, 2) -> (3, 2) -> (3, 3)
    (0, 0) -> (1, 0) -> (1, 1) -> (2, 1) -> (2, 2) -> (2, 3) -> (3, 3)
    (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> (2, 2) -> (3, 2) -> (3, 3)
    (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> (2, 2) -> (2, 3) -> (3, 3)
    (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> (1, 3) -> (2, 3) -> (3, 3)
    (0, 0) -> (0, 1) -> (1, 1) -> (2, 1) -> (3, 1) -> (3, 2) -> (3, 3)
    (0, 0) -> (0, 1) -> (1, 1) -> (2, 1) -> (2, 2) -> (3, 2) -> (3, 3)
    (0, 0) -> (0, 1) -> (1, 1) -> (2, 1) -> (2, 2) -> (2, 3) -> (3, 3)
    (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> (2, 2) -> (3, 2) -> (3, 3)
    (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> (2, 2) -> (2, 3) -> (3, 3)
    (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> (1, 3) -> (2, 3) -> (3, 3)
    (0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> (2, 2) -> (3, 2) -> (3, 3)
    (0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> (2, 2) -> (2, 3) -> (3, 3)
    (0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> (1, 3) -> (2, 3) -> (3, 3)
    (0, 0) -> (0, 1) -> (0, 2) -> (0, 3) -> (1, 3) -> (2, 3) -> (3, 3)
    Total count is : 20
    

    【讨论】:

      【解决方案2】:

      由于您正在学习如何使用 Java,我建议您采用更面向对象的方法。

      1. 创建一个包含 x、y 位置的 Location 对象
      2. 每个可能的路径都将表示为 List&lt;Location&gt;...(或者,扩展 AbstractList 以创建自己的 Path 类。)
      3. 递归函数采用额外的路径参数 (List&lt;Location&gt;) 并返回路径列表 (List&lt;List&lt;Location&gt;&gt;)
      4. 在递归调用中,创建路径参数的新副本,以便递归调用修改自己的副本,而不是共享副本
      5. 双递归调用返回的两个路径列表组合成一个路径列表然后返回
      6. 另一种方法可以遍历List&lt;List&lt;Location&gt;&gt;,打印每一个
      7. 位置应该定义一个以所需格式打印的toString 方法

      【讨论】:

      • 第 5 点是什么?我将如何合并两个路径列表?什么是组合数组?我应该将其设为 List> 吗?
      • @SatyaveerSingh return result1.addAll(result2); // List&lt;List&lt;Location&gt;&gt;
      【解决方案3】:

      我们可以使用数学来计算方式的数量。如果你在 (0, 0) 并且你想去 (N, M)。你应该把 M 拿起来,把 N 拿起来。所以就变成了这样一个问题:在N+M个动作中,你选择其中N个是对的,其余的都是向上的。所以总数是(N+M)! / (N!*M!)

      如果你想打印所有的方式。你可以使用 dp 来做到这一点。但是会消耗很多内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2019-07-21
        • 2023-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多