【问题标题】:Find "path" in 2D array where path cells sum equals to "sum"在二维数组中查找“路径”,其中路径单元总和等于“总和”
【发布时间】:2019-10-17 10:32:05
【问题描述】:

给定二维正整数数组。 “路径”是相邻单元格的集合。两个单元格仅从右/左/上/下(无对角线)相邻。

任务是编写一个函数,接收一个二维数组mat、一个整数sum和一个二维数组path(大小与mat相同-空数组全为零)。

该函数应检查路径是否存在于单元格总和等于sum 的位置,如果存在则返回 true,否则返回 false。

数组path 将标记路径(如果与1 一起存在)。

例如,如果mat 是:

sum=4

那么path 可以是这三个之一:

我的代码:

public static void main(String[] args) 
{
    int[][] mat={{2,41,3,14},
                 {2,1,24,7},
                 {2,15,10,54},
                 {63,22,2,4}};

    int[][] path={{0,0,0,0},
                  {0,0,0,0},
                  {0,0,0,0},
                  {0,0,0,0}};
    findSum(mat,4,path);
    //print(mat);
    print(path);
}
public static boolean findSum (int mat[][], int sum, int path[][])
{
    return findSum(mat,sum,path,0,0);
}

public static boolean findSum (int mat[][], int sum, int path[][],int i,int j)
{
    if(sum==0)                      
        return true;

    if(i==mat[0].length||j==mat[1].length)
        return false;       
    boolean result=findSum(mat,sum-mat[i][j],path,i,j+1)||findSum(mat,sum-mat[i][j],path,i+1,j);

    if(result)
        path[i][j]=1;
    return result;

}
private static void print(int[][] arr)
{
    for(int i=0;i<arr[0].length;i++)
    {
        for(int j=0;j<arr[0].length;j++)
        {
            System.out.print(arr[i][j]+" ");
        }
        System.out.println();
    }
}

我的代码只有在路径从 (0,0) 开始但不适用于其他路径时才能正常工作,例如,即使有这样的sum=16,它也不起作用(路径数组全为零)路径。

注意:

  • 函数必须是递归的——根本没有循环。
  • 不允许使用全局变量(打印数组不是问题的一部分——仅用于测试,因此存在循环)

【问题讨论】:

  • 是寻找可能路径或查看给定路径和总和是否对给定矩阵有效的工作?
  • 任务是编写一个递归函数,接收mat(正整数的二维数组)、sumpath(零的二维数组)。如果有一条路径他的总和等于给定的sum 变量,则该函数应返回true
  • 我们为什么要在路径中设置值呢?
  • sum 必须重置,并且您必须对每个单元格再次执行整个检查。此外,如果路径的形状像字母 J,这种仅向右和向下移动的方法将不起作用。
  • 您只能找到从左上角单元格开始的路径,因为这是您开始搜索的唯一位置,而这恰好发生在 findSum(mat,sum,path,0,0);

标签: java recursion backtracking


【解决方案1】:

好问题...这是答案。这是一个有趣的代码挑战;)

public static void main(String[] args) 
{
    int[][] mat={{2,41,3,14},
                 {2,1,24,7},
                 {2,15,10,54},
                 {63,22,2,4}};

    int[][] path={{0,0,0,0},
                  {0,0,0,0},
                  {0,0,0,0},
                  {0,0,0,0}};

    if ( findSum(mat,22,path) ) print(path);
    else System.out.println("No path found");
}
public static boolean findSum (int mat[][], int sum, int path[][])
{
    return startPath(mat, sum, path, -1, 0);
}

// Recursively check every possible starting point
public static boolean startPath(int mat[][], int sum, int path[][], int y, int x)
{
    // Iterate y, goto next column if necessary
    if (++y == mat.length) {
        y = 0;
        ++x;
    }

    if (x == mat[0].length) // Bounds check
        return false;

    if (findSum(mat, sum, path, y, x)) // We've found a successful start point!
    {
        System.out.println("A successful path starts at " + x + ", " + y);
        return true;
    }

    return startPath(mat, sum, path, y, x); // We'll have to keep looking
}

public static boolean findSum (int mat[][], int sum, int path[][], int i, int j)
{
    if(i==mat[0].length || j==mat[1].length || i<0 || j<0) // Bounds check
        return false;

    if (path[i][j] == 1) // Backtracking check
        return false;

    sum -= mat[i][j]; // Decrement sum

    if (sum >= 0) { // More to go? look around
        path[i][j] = 1;

        if (sum == 0) return true; // We made it!

         // If any path finds the end, don't try other paths
        boolean result = findSum(mat, sum, path, i+1, j);
        if (result) return true;
        result = findSum(mat, sum, path, i, j+1);
        if (result) return true;
        result = findSum(mat, sum, path, i-1, j);
        if (result) return true;
        result = findSum(mat, sum, path, i, j-1);

         // There was no successful paths, this is a dead end
        if (!result) path[i][j] = 0;
        return result;
    } else { // We're negative, overshot it
        return false;
    }
}

private static void print(int[][] arr)
{
    for(int i=0;i<arr[0].length;i++)
    {
        for(int j=0;j<arr[0].length;j++)
        {
            System.out.print(arr[i][j]+" ");
        }
        System.out.println();
    }
}

顺便说一句,在检查多维数组维度时,您的意思是执行arr.length and arr[0].length,但您正在执行arr[0].length and arr[1].length,这将获得两次相同的维度,如果数组不是正方形,则会导致错误。

我还允许向任何方向移动,方法是使用预期的路径来防止再次检查同一节点。这可能是一个布尔数组。抱歉,如果我的 x/y 递归看起来很粗糙......我真的更喜欢循环或 .forEach 或 => 或 .map ......

-1, 0 可以使用可选参数进行清理,而不是在第一次遍历时进行迭代。

如果您发现任何错误或边缘情况,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多