对 int[] visited 的讨论

对Node节点的定义

在一般情况下,图中的节点通过 id 字段来进行设置。例如,题目中给定图中节点编号为 0 到 n-1,此时可以认为有如下的一个结点类Node

class Node{
    public int id;
    // 省略构造函数...
}

但是,在用字符表示的矩阵图中,一般有 x 和 y 两个下标,上、下、左、右四种移动方式,此时可以认为结点类Node定义如下

class Node{
    public int x;
    public int y;
}

另外,在 LeetCode 864 中,出现这样的情况,某个位置点并不是只能访问一次,即可以有条件的重复访问(无论什么情况下,无条件的重复访问必定陷入死循环)。因此需要分析出,在什么情况下允许重复访问是解决问题的开始。这题是在获取到新的锁之后。

对于可重复访问节点的问题,我们需要在基本的节点定义下为节点添加一些额外的信息。基本的节点定义中只包含位置信息,例如 x 和 y;对于可重复访问问题,仅仅只考虑位置关系就会陷入死循环。

假设一个场景,有份公用的共享资源(假设为节点[x,y]),某杠精先占用该资源一段时间(访问[x,y]节点),然后到期后又再次占用该资源(再次访问[x,y]节点),有人对他这种长期占用的行为不满,但是杠精可以有理有据地反驳:这个资源允许我重复访问啊!

因此,规则制定者为了完善可重复访问这一规则,例如:上一次访问的人不可以重复访问。如果为了实现这一效果,就需要在节点的定义中添加一个额外字段:上一次访问人。当然,随着规则的复杂化,这个额外字段可以有多个。这些额外字段和位置信息[x,y]无关,统称为状态信息。

总得来说,可重复访问要避免陷入死循环,所以必定是有条件的可重复访问。所以,可重复访问的完整表述应该是:在不同状态信息下,可以重复访问相同的位置;而在相同的状态信息下,不可以重复访问相同的位置。只有引入状态信息,才能说明今天的我Node n1和昨天的我不是同一个我Node n2,即 n1.equals(n2) === false

class Node{
    public int x;
    public int y;
    public int state0;
    public int state1;
    //...
    //也可以直接定义成public int[] states;
}

对 int[] visited 的定义

visited 访问数组需要跟随 Node 节点的定义。visited 数组的最泛化的形式应该是 Map<Node, Object> visited,如果对于 visited 中保存的值不关心,那么可以退化成 Set<Node> visited,这和 boolean[] visited 相对应。

Map<Node, Object> visited 究竟是 int[] visited 还是 int[][] visited 又或者是 int[][][] visited 则完全取决于包含状态信息在内的 Node 节点如何定义。而map中保存的object值和数组中保存的值对应,具体保存什么东西取决于具体问题。例如,限制每个节点的访问次数不能超过3次,那么visited应该保存节点的访问次数。

总结来说,visited 访问数组并不仅仅表示是否访问某个节点,广义来讲,其可以用来保存每一个状态结点的信息

状态节点说明不仅仅是位置信息,t1时刻访问[x, y] 节点和 t2 时刻访问 [x, y] 节点,如果包含时间信息,那么[x,y,t1]和[x,y,t2]被认为是两个不同的状态节点

要保存的节点信息取决于向visited中放入的是什么内容。放入true、false则代表是否访问过该节点;放入访问次数则代表访问该节点的次数;还可以放入一个自定义的类型对象。


   转载规则


《》 熊水斌 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Shell脚本脚本以#!/bin/bash开头 执行方式 直接使用文件名执行: 文件需要执行权限 以bash xxx.sh来执行, 本质上是bash解析器去执行, 文件作为一个输入, 因此可以不需要执行权限 变量系统变量 自定义变量
2023-06-02
下一篇 
步骤: 通过根节点在前序遍历中的索引rootIndexAtPreorder找出根节点的值preorder[rootIndexAtPreorder] 借助前面生成的HashMap, 通过根节点的值反向找出根节点在中序序列inorder中的
2023-05-28
  目录