【每日一题Day335】LC1993树上的操作 | dfs

简介: 【每日一题Day335】LC1993树上的操作 | dfs

树上的操作【LC1993】

给你一棵 n 个节点的树,编号从 0n - 1 ,以父节点数组 parent 的形式给出,其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点,所以 parent[0] = -1

因为它没有父节点。你想要设计一个数据结构实现树里面对节点的加锁,解锁和升级操作。

数据结构需要支持如下函数:

  • **Lock:**指定用户给指定节点 上锁 ,上锁后其他用户将无法给同一节点上锁。只有当节点处于未上锁的状态下,才能进行上锁操作。
  • **Unlock:**指定用户给指定节点 解锁 ,只有当指定节点当前正被指定用户锁住时,才能执行该解锁操作。
  • Upgrade:

指定用户给指定节点

上锁

,并且将该节点的所有子孙节点

解锁

。只有如下 3 个条件

全部

Upgrade:

指定用户给指定节点

上锁

,并且将该节点的所有子孙节点

解锁

。只有如下 3 个条件

全部

请你实现 LockingTree 类:


LockingTree(int[] parent) 用父节点数组初始化数据结构。

lock(int num, int user) 如果 id 为 user 的用户可以给节点 num 上锁,那么返回 true ,否则返回 false 。如果可以执行此操作,节点 num 会被 id 为 user 的用户 上锁 。

  • unlock(int num, int user) 如果 id 为 user 的用户可以给节点 num 解锁,那么返回 true ,否则返回 false 。如果可以执行此操作,节点 num 变为 未上锁 状态。
  • upgrade(int num, int user) 如果 id 为 user 的用户可以给节点 num 升级,那么返回 true ,否则返回 false 。如果可以执行此操作,节点 num 会被 升级


  • 思路使用数组记录每个节点的父节点以及上锁状态,并使用list记录每个节点的孩子节点,方便dfs操作
  • lock和unlock函数进行简单判断即可
  • upgrade函数需要判断祖先节点是否上锁,再通过dfs判断是否有上锁的孩子节点,并将其解锁
  • 实现
class LockingTree {
    // 记录每个节点的根节点以及加锁状态
    int[] locked;
    int[] parent;
    int n;
    List<Integer>[] children;
    public LockingTree(int[] parent) {
        this.n = parent.length;
        this.parent = parent;
        this.locked = new int[n];
        this.children = new List[n];
        Arrays.fill(locked, -1);
        Arrays.setAll(children, e -> new ArrayList<>());
        for (int i = 0; i < n; i++){
            if (parent[i] != -1){
                children[parent[i]].add(i);
            }
        }
    }
    public boolean lock(int num, int user) {
        if (locked[num] != -1) return false;
        locked[num] = user;
        return true;
    }
    public boolean unlock(int num, int user) {
        if (locked[num] == user){
            locked[num] = -1;
            return true;
        }
        return false;
    }
    public boolean upgrade(int num, int user) {
        if (locked[num] != -1) return false;
        // 判断祖先节点是否上锁
        int p = parent[num];
        while (p != -1){
            if (locked[p] != -1) return false;
            p = parent[p];
        }
        // 判断是否有子孙节点加锁了,并给子孙节点解锁
        boolean[] res = {false};
        dfs(num, res);
        if (res[0] == false) return false;
        locked[num] = user;
        return true;
    }
    public void dfs(int p, boolean[] lock){
        for (int u : children[p]){
            if (locked[u] != -1){
                lock[0] = true;
                locked[u] = -1;               
            }
            dfs(u, lock);
        }
    }
}
/**
 * Your LockingTree object will be instantiated and called as such:
 * LockingTree obj = new LockingTree(parent);
 * boolean param_1 = obj.lock(num,user);
 * boolean param_2 = obj.unlock(num,user);
 * boolean param_3 = obj.upgrade(num,user);
 */

image.png

目录
相关文章
|
4月前
【每日一题Day305】LC1448统计二叉树中好节点的数目 | dfs
【每日一题Day305】LC1448统计二叉树中好节点的数目 | dfs
36 0
|
4月前
【每日一题Day222】LC1110删点成林 | dfs后序
【每日一题Day222】LC1110删点成林 | dfs后序
43 0
|
4月前
【每日一题Day214】LC1080根到叶路径上的不足节点 | 递归
【每日一题Day214】LC1080根到叶路径上的不足节点 | 递归
43 0
|
4月前
【每日一题Day212】LC1373二叉搜索子树的最大键值和 | dfs+树形dp
【每日一题Day212】LC1373二叉搜索子树的最大键值和 | dfs+树形dp
27 0
|
4月前
【每日一题Day287】LC24 两两交换链表中的节点 | 模拟 递归
【每日一题Day287】LC24 两两交换链表中的节点 | 模拟 递归
38 0
|
4月前
【每日一题Day285】LC980不同路径 III | 回溯
【每日一题Day285】LC980不同路径 III | 回溯
49 0
|
4月前
|
人工智能 BI
【每日一题Day232】LC2699修改图中的边权 |最短路径
【每日一题Day232】LC2699修改图中的边权 |最短路径
33 0
|
4月前
|
人工智能 BI
【每日一题Day267】LC834树中距离之和 | 换根dp
【每日一题Day267】LC834树中距离之和 | 换根dp
38 0
|
4月前
【每日一题Day295】LC617合并二叉树 | DFS BFS
【每日一题Day295】LC617合并二叉树 | DFS BFS
22 0
|
4月前
|
存储 人工智能 BI
【每日一题Day216】LC1377 T 秒后青蛙的位置 | BFS DFS
【每日一题Day216】LC1377 T 秒后青蛙的位置 | BFS DFS
46 0