636 words
3 minutes
C_code_practise
2025-04-18
No Tags

今天是2025年4月18日,今天练习一道medium。

你正在维护一个项目,该项目有 n 个方法,编号从 0 到 n - 1。

给你两个整数 n 和 k,以及一个二维整数数组 invocations,其中 invocations[i] = [ai, bi] 表示方法 ai 调用了方法 bi。

已知如果方法 k 存在一个已知的 bug。那么方法 k 以及它直接或间接调用的任何方法都被视为 可疑方法 ,我们需要从项目中移除这些方法。

只有当一组方法没有被这组之外的任何方法调用时,这组方法才能被移除。

返回一个数组,包含移除所有 可疑方法 后剩下的所有方法。你可以以任意顺序返回答案。如果无法移除 所有 可疑方法,则 不 移除任何方法。

#include <vector>
class Solution {
public:
    vector<int> remainingMethods(int n, int k, vector<vector<int>>& invocations) {

关于C++的vector,学习一下它和python的list的不同,C++的vector是提前规定类型的,而python的list是动态的。而操作来说,vector有push_back(),pop_back()

得到一个n functions 需要维护 with label 0 to n-1. input是一个n,k,一个[ai,bi]的二维数组。有点像一个linked list, 但是是二维的。 给了一个例子n=4,k=1,invocations=[[0,1],[1,2],[3,2]] output:[0,1,2,3] 有点像esbmc,尽管需要free memory, 但是由于被后一个函数调用,所以目前不能free.

我们首先要标记哪些函数是可疑的。

class Solution {
public:
    vector<int> remainingMethods(int n, int k, vector<vector<int>>& invocations) {
        // 构建邻接表表示调用关系
        vector<vector<int>> graph(n);
        for (const auto& e : invocations) {
            graph[e[0]].push_back(e[1]);
        }
        
        // 使用DFS标记所有从k可达的节点为可疑
        vector<bool> isSuspicious(n, false);
        function<void(int)> dfs = [&](int node) {
            isSuspicious[node] = true;
            for (int next : graph[node]) {
                if (!isSuspicious[next]) {
                    dfs(next);
                }
            }
        };
        
        dfs(k);
        
        // 检查是否有非可疑方法调用可疑方法
        for (const auto& e : invocations) {
            if (!isSuspicious[e[0]] && isSuspicious[e[1]]) {
                // 如果有非可疑方法调用可疑方法,返回所有方法
                vector<int> allMethods(n);
                for (int i = 0; i < n; i++) {
                    allMethods[i] = i;
                }
                return allMethods;
            }
        }
        
        // 否则,返回所有非可疑方法
        vector<int> result;
        for (int i = 0; i < n; i++) {
            if (!isSuspicious[i]) {
                result.push_back(i);
            }
        }
        return result;
    }
};

这样的题目,特点是包含方法调用关系或者依赖关系,就应该想到图论。 效率相当低,看了别人的解题思路是使用DFS进行标记,而不是两次遍历。

TODO:

  1. 学习一下C++的DFS和BFS
  2. 学习一下C++的图论
C_code_practise
https://lukew1999.github.io/posts/c_code_practise/
Author
Weiqi Wang
Published at
2025-04-18