列表

详情


1993. 树上的操作

给你一棵 n 个节点的树,编号从 0 到 n - 1 ,以父节点数组 parent 的形式给出,其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点,所以 parent[0] = -1 ,因为它没有父节点。你想要设计一个数据结构实现树里面对节点的加锁,解锁和升级操作。

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

请你实现 LockingTree 类:

 

示例 1:

输入:
["LockingTree", "lock", "unlock", "unlock", "lock", "upgrade", "lock"]
[[[-1, 0, 0, 1, 1, 2, 2]], [2, 2], [2, 3], [2, 2], [4, 5], [0, 1], [0, 1]]
输出:
[null, true, false, true, true, true, false]

解释:
LockingTree lockingTree = new LockingTree([-1, 0, 0, 1, 1, 2, 2]);
lockingTree.lock(2, 2);    // 返回 true ,因为节点 2 未上锁。
                           // 节点 2 被用户 2 上锁。
lockingTree.unlock(2, 3);  // 返回 false ,因为用户 3 无法解锁被用户 2 上锁的节点。
lockingTree.unlock(2, 2);  // 返回 true ,因为节点 2 之前被用户 2 上锁。
                           // 节点 2 现在变为未上锁状态。
lockingTree.lock(4, 5);    // 返回 true ,因为节点 4 未上锁。
                           // 节点 4 被用户 5 上锁。
lockingTree.upgrade(0, 1); // 返回 true ,因为节点 0 未上锁且至少有一个被上锁的子孙节点(节点 4)。
                           // 节点 0 被用户 1 上锁,节点 4 变为未上锁。
lockingTree.lock(0, 1);    // 返回 false ,因为节点 0 已经被上锁了。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class LockingTree { public: LockingTree(vector<int>& parent) { } bool lock(int num, int user) { } bool unlock(int num, int user) { } bool upgrade(int num, int user) { } }; /** * Your LockingTree object will be instantiated and called as such: * LockingTree* obj = new LockingTree(parent); * bool param_1 = obj->lock(num,user); * bool param_2 = obj->unlock(num,user); * bool param_3 = obj->upgrade(num,user); */

javascript 解法, 执行用时: 336 ms, 内存消耗: 54.1 MB, 提交时间: 2023-09-23 00:15:10

/**
 * @param {number[]} parent
 */
var LockingTree = function(parent) {
    const n = parent.length;
    this.parent = parent;
    this.lockNodeUser = new Array(n).fill(-1);
    this.children = new Array(n).fill(0).map(() => new Array());
    for (let i = 0; i < n; i++) {
        const p = parent[i];
        if (p != -1) {
            this.children[p].push(i);
        }
    }
};

/** 
 * @param {number} num 
 * @param {number} user
 * @return {boolean}
 */
LockingTree.prototype.lock = function(num, user) {
    if (this.lockNodeUser[num] == -1) {
        this.lockNodeUser[num] = user;
        return true;
    }
    return false;
};

/** 
 * @param {number} num 
 * @param {number} user
 * @return {boolean}
 */
LockingTree.prototype.unlock = function(num, user) {
    if (this.lockNodeUser[num] == user) {
        this.lockNodeUser[num] = -1
        return true;
    }
    return false;
};

/** 
 * @param {number} num 
 * @param {number} user
 * @return {boolean}
 */
LockingTree.prototype.upgrade = function(num, user) {
    res = this.lockNodeUser[num] == -1 && !this.hasLockedAncestor(num)
                                       && this.checkAndUnlockDescendant(num)
    if (res) {
        this.lockNodeUser[num] = user;
    }
    return res;
};

/** 
 * @param {number} num 
 * @return {boolean}
 */
LockingTree.prototype.hasLockedAncestor = function(num) {
    num = this.parent[num];
    while (num != -1) {
        if (this.lockNodeUser[num] != -1) {
            return true;
        } else {
            num = this.parent[num];
        }
    }
    return false;
}

/** 
 * @param {number} num 
 * @return {boolean}
 */
LockingTree.prototype.checkAndUnlockDescendant = function(num) {
    res = this.lockNodeUser[num] != -1;
    this.lockNodeUser[num] = -1;
    for (const child of this.children[num]) {
        res |= this.checkAndUnlockDescendant(child);
    }
    return res;
}

/**
 * Your LockingTree object will be instantiated and called as such:
 * var obj = new LockingTree(parent)
 * var param_1 = obj.lock(num,user)
 * var param_2 = obj.unlock(num,user)
 * var param_3 = obj.upgrade(num,user)
 */

golang 解法, 执行用时: 252 ms, 内存消耗: 7.5 MB, 提交时间: 2023-09-23 00:13:11

type LockingTree struct {
    parent []int
    lockNodeUser []int
    children [][]int
}

func Constructor(parent []int) LockingTree {
    n := len(parent)
    lockNodeUser := make([]int, n)
    children := make([][]int, n)
    for i := 0; i < n; i++ {
        lockNodeUser[i] = -1
        p := parent[i]
        if p != -1 {
            children[p] = append(children[p], i)
        }
    }
    return LockingTree{parent, lockNodeUser, children}
}

func (this *LockingTree) Lock(num int, user int) bool {
    if this.lockNodeUser[num] == -1 {
        this.lockNodeUser[num] = user
        return true
    } 
    return false
}

func (this *LockingTree) Unlock(num int, user int) bool {
    if this.lockNodeUser[num] == user {
        this.lockNodeUser[num] = -1
        return true
    }
    return false
}

func (this *LockingTree) Upgrade(num int, user int) bool {
    res := this.lockNodeUser[num] == -1 && !this.hasLockedAncestor(num) && this.checkAndUnlockDescendant(num)
    if res {
        this.lockNodeUser[num] = user
    }
    return res
}

func (this *LockingTree) hasLockedAncestor(num int) bool {
    num = this.parent[num]
    for num != -1 {
        if this.lockNodeUser[num] != -1 {
            return true
        }
        num = this.parent[num]
    }
    return false
}

func (this *LockingTree) checkAndUnlockDescendant(num int) bool {
    res := false
    if this.lockNodeUser[num] != -1 {
        res = true
    }
    this.lockNodeUser[num] = -1
    for _, child := range this.children[num] {
        if this.checkAndUnlockDescendant(child) {
            res = true
        }
    }            
    return res
}

/**
 * Your LockingTree object will be instantiated and called as such:
 * obj := Constructor(parent);
 * param_1 := obj.Lock(num,user);
 * param_2 := obj.Unlock(num,user);
 * param_3 := obj.Upgrade(num,user);
 */

cpp 解法, 执行用时: 380 ms, 内存消耗: 120.6 MB, 提交时间: 2023-09-23 00:12:50

class LockingTree {
public:
    LockingTree(vector<int>& parent) {
        int n = parent.size();
        this->parent = parent;
        this->lockNodeUser = vector<int>(n, -1);
        this->children = vector<vector<int>>(n);
        for (int i = 0; i < n; i++) {
            int p = parent[i];
            if (p != -1) {
                children[p].emplace_back(i);
            }
        }
    }
    
    bool lock(int num, int user) {
        if (lockNodeUser[num] == -1) {
            lockNodeUser[num] = user;
            return true;
        } 
        return false;
    }
    
    bool unlock(int num, int user) {
        if (lockNodeUser[num] == user) {
            lockNodeUser[num] = -1;
            return true;
        }
        return false;
    }
    
    bool upgrade(int num, int user) {
        bool res = lockNodeUser[num] == -1 \
                   && !hasLockedAncestor(num) \
                   && checkAndUnlockDescendant(num);
        if (res) {
            lockNodeUser[num] = user;
        }
        return res;
    }

    bool hasLockedAncestor(int num) {
        num = parent[num];
        while (num != -1) {
            if (lockNodeUser[num] != -1) {
                return true;
            }
            num = parent[num];
        }
        return false;
    }
        
    bool checkAndUnlockDescendant(int num) {
        bool res = lockNodeUser[num] != -1;
        lockNodeUser[num] = -1;
        for (int child : children[num]) {
            res |= checkAndUnlockDescendant(child);
        }            
        return res;
    }
        
private:
    vector<int> parent;
    vector<int> lockNodeUser;
    vector<vector<int>> children;
};

/**
 * Your LockingTree object will be instantiated and called as such:
 * LockingTree* obj = new LockingTree(parent);
 * bool param_1 = obj->lock(num,user);
 * bool param_2 = obj->unlock(num,user);
 * bool param_3 = obj->upgrade(num,user);
 */

java 解法, 执行用时: 113 ms, 内存消耗: 46.9 MB, 提交时间: 2023-09-23 00:12:29

class LockingTree {
    private int[] parent;
    private int[] lockNodeUser;
    private List<Integer>[] children;

    public LockingTree(int[] parent) {
        int n = parent.length;
        this.parent = parent;
        this.lockNodeUser = new int[n];
        Arrays.fill(this.lockNodeUser, -1);
        this.children = new List[n];
        for (int i = 0; i < n; i++) {
            this.children[i] = new ArrayList<Integer>();
        }
        for (int i = 0; i < n; i++) {
            int p = parent[i];
            if (p != -1) {
                children[p].add(i);
            }
        }
    }

    public boolean lock(int num, int user) {
        if (lockNodeUser[num] == -1) {
            lockNodeUser[num] = user;
            return true;
        } 
        return false;
    }

    public boolean unlock(int num, int user) {
        if (lockNodeUser[num] == user) {
            lockNodeUser[num] = -1;
            return true;
        }
        return false;
    }

    public boolean upgrade(int num, int user) {
        boolean res = lockNodeUser[num] == -1 && !hasLockedAncestor(num) && checkAndUnlockDescendant(num);
        if (res) {
            lockNodeUser[num] = user;
        }
        return res;
    }

    private boolean hasLockedAncestor(int num) {
        num = parent[num];
        while (num != -1) {
            if (lockNodeUser[num] != -1) {
                return true;
            }
            num = parent[num];
        }
        return false;
    }

    private boolean checkAndUnlockDescendant(int num) {
        boolean res = lockNodeUser[num] != -1;
        lockNodeUser[num] = -1;
        for (int child : children[num]) {
            res |= checkAndUnlockDescendant(child);
        }            
        return res;
    }
}

/**
 * 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);
 */

python3 解法, 执行用时: 1064 ms, 内存消耗: 19.7 MB, 提交时间: 2023-09-23 00:12:10

class LockingTree:

    def __init__(self, parent: List[int]):
        n = len(parent)
        self.parent = parent
        self.lockNodeUser = [-1] * n
        self.children = [[] for _ in range(n)]
        for node, p in enumerate(parent):
            if p != -1:
                self.children[p].append(node)

    def lock(self, num: int, user: int) -> bool:
        if self.lockNodeUser[num] == -1:
            self.lockNodeUser[num] = user
            return True
        else:
            return False

    def unlock(self, num: int, user: int) -> bool:
        if self.lockNodeUser[num] == user:
            self.lockNodeUser[num] = -1
            return True
        else:
            return False

    def upgrade(self, num: int, user: int) -> bool:
        res = self.lockNodeUser[num] == -1 and not self.hasLockedAncestor(num) and self.checkAndUnlockDescendant(num)
        if res:
            self.lockNodeUser[num] = user
        return res
    
    def hasLockedAncestor(self, num: int) -> bool:
        num = self.parent[num]
        while num != -1:
            if self.lockNodeUser[num] != -1:
                return True
            else:
                num = self.parent[num]
        return False
    
    def checkAndUnlockDescendant(self, num:int) -> bool:
        res = self.lockNodeUser[num] != -1
        self.lockNodeUser[num] = -1
        for child in self.children[num]:
            res |= self.checkAndUnlockDescendant(child)
        return res

# Your LockingTree object will be instantiated and called as such:
# obj = LockingTree(parent)
# param_1 = obj.lock(num,user)
# param_2 = obj.unlock(num,user)
# param_3 = obj.upgrade(num,user)

上一题