2023-09-23力扣每日一题

链接:

1993. 树上的操作

题意

  • **Lock:**指定用户给指定节点 上锁 ,上锁后其他用户将无法给同一节点上锁。只有当节点处于未上锁的状态下,才能进行上锁操作。
  • **Unlock:**指定用户给指定节点 解锁 ,只有当指定节点当前正被指定用户锁住时,才能执行该解锁操作。
  • Upgrade:指定用户给指定节点 上锁 ,并且将该节点的所有子孙节点 解锁 。只有如下 3 个条件全部满足时才能执行升级操作:
    • 指定节点当前状态为未上锁。
    • 指定节点至少有一个上锁状态的子孙节点(可以是 任意 用户上锁的)。
    • 指定节点没有任何上锁的祖先节点。

基础的类设计,用到的是递归/dfs

可以用递归优化子节点的查询,同时把修改子节点的值

复制代码
 bool check2(int num)
    {
        bool ans=false;
        for(auto s:son[num])
        {
            ans |= book[s]!=0;
            book[s]=0;
            ans |= check2(s);
        }

        return ans;
    }

实际代码:

c++ 复制代码
class LockingTree {
public:
    vector<int>parent;
    vector<vector<int>>son;
    vector<int>book;
    LockingTree(vector<int>& parent) {
        this->parent=parent;
        book.resize(parent.size());
        son.resize(parent.size());
        
        for(int i=0;i<parent.size();i++)
        {
            if(parent[i]>=0)
            {
                son[parent[i]].push_back(i);
            }
        }
    }
    
    bool lock(int num, int user) {
        if(book[num]==0)
        {
            book[num]=user;
            return true;
        }

        return false;
    }
    
    bool unlock(int num, int user) {
        if(book[num]==user)
        {
            book[num]=0;
            return true;
        }

        return false;
    }
    
    bool upgrade(int num, int user) {
        if(book[num]==0)
        {
            if(check1(num) && check2(num))
            {
                book[num]=user;
                //clear(num);
                return true;
            }
        }

        return false;
    }

    bool check2(int num)
    {
        bool ans=false;
        vector<int>begin=son[num];
        while(true)
        {
            vector<int>next;
            for(auto b:begin)
            {
                if(book[b])
                {
                    ans=true;
                    book[b]=0;
                }
                for(auto bson:son[b])
                {
                    next.push_back(bson);
                }
            }
            if(next.empty()) break;
            begin=next;
        }

        return ans;
    }

    bool check1(int num)
    {
        while(parent[num]!=-1)
        {
            num=parent[num];
            if(book[num]) return false;
        }

        return true;
    }

    void clear(int num)
    {
        vector<int>begin=son[num];
        while(true)
        {
            vector<int>next;
            for(auto b:begin)
            {
                if(book[b]) book[b]=0;
                for(auto bson:son[b])
                {
                    next.push_back(bson);
                }
            }
            if(next.empty()) break;
            begin=next;
        }
    }
};

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

限制:

  • n == parent.length
  • 2 <= n <= 2000
  • 对于 i != 0 ,满足 0 <= parent[i] <= n - 1
  • parent[0] == -1
  • 0 <= num <= n - 1
  • 1 <= user <= 104
  • parent 表示一棵合法的树。
  • lockunlockupgrade 的调用 总共 不超过 2000 次。
相关推荐
牛客企业服务15 分钟前
2025年AI面试推荐榜单,数字化招聘转型优选
人工智能·python·算法·面试·职场和发展·金融·求职招聘
糖葫芦君1 小时前
Policy Gradient【强化学习的数学原理】
算法
向阳@向远方3 小时前
第二章 简单程序设计
开发语言·c++·算法
github_czy3 小时前
RRF (Reciprocal Rank Fusion) 排序算法详解
算法·排序算法
许愿与你永世安宁4 小时前
力扣343 整数拆分
数据结构·算法·leetcode
爱coding的橙子4 小时前
每日算法刷题Day42 7.5:leetcode前缀和3道题,用时2h
算法·leetcode·职场和发展
满分观察网友z5 小时前
从一次手滑,我洞悉了用户输入的所有可能性(3330. 找到初始输入字符串 I)
算法
YuTaoShao5 小时前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
Heartoxx5 小时前
c语言-指针(数组)练习2
c语言·数据结构·算法
大熊背5 小时前
图像处理专业书籍以及网络资源总结
人工智能·算法·microsoft