Algorithm 在矩阵中查找最大可访问节点
我在一次编码测试中遇到了这个问题,没有找到有效的方法 给定矩阵a,移动规则如下:Algorithm 在矩阵中查找最大可访问节点,algorithm,matrix,data-structures,Algorithm,Matrix,Data Structures,我在一次编码测试中遇到了这个问题,没有找到有效的方法 给定矩阵a,移动规则如下: 只能从任何元素向右或向下移动 只能在我们最初开始的元素的同一行或同一列中移动 只有当元素的值小于起始元素的值时,才能访问或跨越该元素 如果从元素A(i,j)开始,其中i->row和 j->column 注意:必须为每个矩阵元素打印此输出 输入矩阵: 1 2 3 2 3 1 3 1 2 输出: 13 1 3 1 3.1.1 解释:从1(i=0,j=0)行方向,我们无法进一步遍历,因此可访问节点=1 而且,在列方面也是
j->column 注意:必须为每个矩阵元素打印此输出 输入矩阵:
1 2 3
2 3 1
3 1 2 输出:
13
1 3 1
3.1.1 解释:从1(i=0,j=0)行方向,我们无法进一步遍历,因此可访问节点=1
而且,在列方面也是一样的。因此,对于(i=0,j=0),最大总节点数为1 我的做法: 尝试了一个普通的解决方案,其中我们从每个元素遍历右侧和向下的元素,并找到两个可访问元素计数的最大值。 但这是没有效率的。 有人能告诉我一个有效的方法吗。
提前感谢。我认为优化代码的一种方法是使用缓存,下面是该算法的一个小实现
int visited[3][3];
memset(visited, -1, sizeof(visited));
int calculateMaxVisitedNode(int x, int y, int visit_count, int r, int c, int valx, int valy)
{
if(x>r || y>c)
{
return visit_count;
}
if(visited[x][y] != -1)
{
return visited[x][y];
}
int right = 0;
int down = 0;
if(A[valx][valy] > A[x][y+1])
{
right = f(x,y+1,visit_count+1,r,c,valx,valy);
}
if(A[valx][valy] > A[x+1][y])
{
down = f(x+1,y,visit_count+1,r,c,valx,valy);
}
visited[x][y] = max(right, down);
return visited[x][y];
}
所以这里我缓存已经访问过的单元格,所以不需要再次遍历它们。当行数和列数非常高时,这可以显著降低时间复杂度。关键点是,我们永远不能超过大于当前元素的元素,而大元素下方或右侧较小元素的值是无关的(因为当我们越过大元素时,我们也能够根据问题陈述越过所有小元素)
- 对于每个列,从下到上,保留一个堆栈,该堆栈将按降序存储元素及其索引(实际上,我们可以只存储索引,并使用该索引在矩阵中查找元素)
- 对于我们访问的每个元素:
- 从堆栈中弹出元素,直到堆栈中最大的元素大于或等于当前元素(或为空)
- 可以向下访问的单元格数是到堆栈最顶部元素的距离(如果堆栈为空,则是到末尾的所有单元格)
- 将该元素推到堆栈上
- 从右到左重复上述过程,将上述值相加
- 在所有内容中添加1,以包括访问自己的单元格
O(行*列)
这方面的Java代码:
int[][]数组={{{1,2,3},
{2, 3, 1},
{3, 1, 2}};
Stack Stack=new Stack();//只存储索引
int[][]输出=新的int[array.length][array[0.length];
对于(int i=array.length-1;i>=0;i--)//方向不重要
{
stack.clear();
对于(int j=array[0]。长度-1;j>=0;j--)
{
而(!stack.empty()&&array[i][stack.peek()]=0;i--)//方向不重要
{
stack.clear();
对于(int j=array.length-1;j>=0;j--)
{
而(!stack.empty()&&array[stack.peek()][i]
.这种方法有重复。例如,当您计算
[0][2]
元素(即3)时,您已经计算了[1][2]
(即1)。尝试看看是否可以重用信息。@StutiRastogi:这里不是这样,因为您看到了第三条规则。对于[1][2],可访问元素计数只有1(本身)因为下一个向下[2][2]元素=2大于此值。但是对于[0][2],可访问计数为3,因为[1][2],[2][2]两者都较小并包含其自身。否则我可以使用DP。“在元素的行和列中移动,我们从初始位置开始”-这是什么意思?@n.m.这意味着在向右或向下移动时没有锯齿形图案。因此,对于任何节点,两条路径被视为向下(同一列增加行)和向右(同一行增加列)。我认为这将是“在同一行或列内移动”.那是不对的,我想,你犯了与第一条评论相同的错误。我明白你的意思,你说如果通过(0,2)对于我的方法,它将返回2而不是3,这就是该算法的优点…传入visit_count=1而不是0,然后查看magicor如果您知道当前单元格未被考虑,则将+1添加到该方法返回的结果中,但不考虑必须比较下一个值对于第一个值而不是当前值,仍然不好,因为缓存的值是针对特定的valx和valy的,结果取决于它们无法验证这一点,对于1 2,2 2 1,2 1 2输出应为1 1 2,1 2 1,2 1 11@GP007修正了。那应该是112131211
,不是吗?(因为中间元素可以访问自身,1向下和1向右)它将是2,因为我们必须在两个方向上找到两个可能值中的最大可能值。我们只能在一个方向上移动。因此,向右或向下为自身加1和1。@GP007