C++算法:有向图计数优化版原理及实现

简介: C++算法:有向图计数优化版原理及实现

题目

见前面章节。有向图访问计数的原理及C++实现-CSDN博客

第一版

不需要拓扑排序,也不需要并集查找,直接dfs了。完成以下三个职责:

一,DFS那些端点在环上。

二,DFS环上各点此环的长度。

三,DFS非环上各点。

分析

cur是当前dfs的节点,next为edges[cur]。从后向前分析:

判定处理

ret的值

返回值

找到环尾

ret [cur] = NO - mPreNO[cur]

cur

找到环尾,没找到环首

ret [cur] = ret [next]

同dfs(next...)

之前找到环尾和当前环首

环尾已处理,无需处理

-1

之前找到首尾

ret [cur] = ret [next]+1

-1

判定表

条件一

条件二

结果

mPreNO.count(cur)

找到环尾

dfs(next)返回非-1

cur不等于dfs(next)

找到环尾,没找到环首

cur等于dfs(next)

之前找到环尾和当前环首

dfs(next)返回非-1

之前找到首尾

DSF0过程

DFS(0)

不处理

return -1

DFS(1)

ret[1]=2

return 0

DFS(0)

ret[0]=3-1=2

return 0

DFS(1)过程

DFS(1)

不处理

return -1

DFS(0)

ret[0]=2

return 0

DFS(1)

ret[1]=3-1=2

return 0

FFS(2)过程

DFS(2)

ret[2]=3

Return -1

DFS(0)

不处理

return -1

DFS(1)

ret[1]=2

return 0

DFS(0)

ret[0]=3-1=2

return 0

FFS(4)过程

DFS(4)

ret[4]=3

Return -1

DFS(0)

不处理

return -1

DFS(1)

ret[1]=2

return 0

DFS(0)

ret[0]=3-1=2

return 0

FFS(3)过程

DFS(3)

Ret[3]=4

Return -1;

DFS(2)

ret[2]=3

Return -1

DFS(0)

不处理

return -1

DFS(1)

ret[1]=2

return 0

DFS(0)

ret[0]=3-1=2

return 0

核心代码

class Solution {
public:
    vector<int> countVisitedNodes(vector<int>& edges) {
        m_c = edges.size();
        m_edges = edges;
        m_vRet.assign(m_c, -1);
        for (int i = 0; i < m_c; i++)
        {
            std::unordered_map<int, int> mPreNO;
            dfs(i, mPreNO, 1);
        }
        return m_vRet;
    }
    int dfs(int cur,std::unordered_map<int,int>& mPreNO,int iNO)
    {
        if (mPreNO.count(cur))
        {
            m_vRet[cur] = iNO - mPreNO[cur];
            return cur;
        }
        mPreNO[cur] = iNO;
        const auto& next = m_edges[cur];
        const int iRet = dfs(next, mPreNO, iNO + 1);
        if (iRet == cur)
        {
            return -1;//环结束了
        }
        if (-1 == iRet)
        {
            m_vRet[cur] = m_vRet[next]+1;
        }
        else
        {
            m_vRet[cur] = m_vRet[next];
        }
        return iRet;
    }
    vector<int> m_vRet;
    vector<int> m_edges;
    int m_c;
};

记忆化

如果ret[cur]不为-1,说明cur已经处理。如果cur是环上一点,那说明整个环已经处理,返回-1;如果cur,不是环上一点,也返回-1。

时间复杂度

O(n),任意端点,dfs最多执行两次,一次是主动执行,一次是作为出边被执行。

优化后的代码

class Solution {
public:
    vector<int> countVisitedNodes(vector<int>& edges) {
        m_c = edges.size();
        m_edges = edges;
        m_vRet.assign(m_c, -1);
        for (int i = 0; i < m_c; i++)
        {
            std::unordered_map<int, int> mPreNO;
            dfs(i, mPreNO, 1);
        }
        return m_vRet;
    }
    int dfs(int cur,std::unordered_map<int,int>& mPreNO,int iNO)
    {
        if (-1 != m_vRet[cur])
        {
            return -1;
        }
        if (mPreNO.count(cur))
        {
            m_vRet[cur] = iNO - mPreNO[cur];
            return cur;
        }
        mPreNO[cur] = iNO;
        const auto& next = m_edges[cur];
        const int iRet = dfs(next, mPreNO, iNO + 1);
        if (iRet == cur)
        {
            return -1;//环结束了
        }
        if (-1 == iRet)
        {
            m_vRet[cur] = m_vRet[next]+1;
        }
        else
        {
            m_vRet[cur] = m_vRet[next];
        }
        return iRet;
    }
    vector<int> m_vRet;
    vector<int> m_edges;
    int m_c;
};

再次优化后的代码

用数组代替哈希映射,速度似乎没提升。

class Solution {
public:
    vector<int> countVisitedNodes(vector<int>& edges) {
        m_c = edges.size();
        m_edges = edges;
        m_vRet.assign(m_c, -1);
        int vPreNO[100000];
        for (int i = 0; i < m_c; i++)
        {
            vPreNO[i] = -1;
        }
        for (int i = 0; i < m_c; i++)
        {
            dfs(i, vPreNO, 1);
        }
        return m_vRet;
    }
    int dfs(int cur,int* vPreNO,int iNO)
    {
        if (-1 != m_vRet[cur])
        {
            return -1;
        }
        if (-1 != vPreNO [cur])
        {
            m_vRet[cur] = iNO - vPreNO[cur];
            return cur;
        }
        vPreNO[cur] = iNO;
        const auto& next = m_edges[cur];
        const int iRet = dfs(next, vPreNO, iNO + 1);
        if (iRet == cur)
        {
            return -1;//环结束了
        }
        if (-1 == iRet)
        {
            m_vRet[cur] = m_vRet[next]+1;
        }
        else
        {
            m_vRet[cur] = m_vRet[next];
        }
        return iRet;
    }
    vector<int> m_vRet;
    vector<int> m_edges;
    int m_c;
};

注意

如果用vector<int>记录PreNO,则需要在for循环外初始化,如果for循环内初始化,则时间复杂度变为O(n*n)。

测试环境

VS2022 Win10 C++17

下载

源码下载:

【免费】.有向图计数优化版原理及C++实现资源-CSDN文库


其它

视频课程

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。

https://edu.csdn.net/course/detail/38771

我的其它课程

https://edu.csdn.net/lecturer/6176

测试环境

win7 VS2019 C++17 或Win10 VS2022 Ck++17

相关下载

算法精讲《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

相关文章
|
3天前
|
小程序 编译器 Linux
C++ 异常原理:以一个小程序为例
作者在调查某个 bug 时涉及到 C++ 异常,借此机会以本文把 C++ 异常机制梳理清楚供大家参考。
|
2天前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】层次聚类算法的原理与应用
【4月更文挑战第30天】层次聚类是数据挖掘中的聚类技术,无需预设簇数量,能生成数据的层次结构。分为凝聚(自下而上)和分裂(自上而下)两类,常用凝聚层次聚类有最短/最长距离、群集平均和Ward方法。优点是自动确定簇数、提供层次结构,适合小到中型数据集;缺点是计算成本高、过程不可逆且对异常值敏感。在Python中可使用`scipy.cluster.hierarchy`进行实现。尽管有局限,层次聚类仍是各领域强大的分析工具。
|
2天前
|
机器学习/深度学习 算法 前端开发
【Python机器学习专栏】集成学习算法的原理与应用
【4月更文挑战第30天】集成学习通过组合多个基学习器提升预测准确性,广泛应用于分类、回归等问题。主要步骤包括生成基学习器、训练和结合预测结果。算法类型有Bagging(如随机森林)、Boosting(如AdaBoost)和Stacking。Python中可使用scikit-learn实现,如示例代码展示的随机森林分类。集成学习能降低模型方差,缓解过拟合,提高预测性能。
|
3天前
|
消息中间件 算法 Java
C++实时通信优化技术探究
C++实时通信优化技术探究
13 3
|
3天前
|
机器学习/深度学习 算法 数据挖掘
【视频】支持向量机算法原理和Python用户流失数据挖掘SVM实例(下)
【视频】支持向量机算法原理和Python用户流失数据挖掘SVM实例(下)
11 0
|
3天前
|
机器学习/深度学习 算法 搜索推荐
【视频】支持向量机算法原理和Python用户流失数据挖掘SVM实例(上)
【视频】支持向量机算法原理和Python用户流失数据挖掘SVM实例
12 0
|
5天前
|
机器学习/深度学习 数据采集 人工智能
【热门话题】AI作画算法原理解析
本文解析了AI作画算法的原理,介绍了基于机器学习和深度学习的CNNs及GANs在艺术创作中的应用。从数据预处理到模型训练、优化,再到风格迁移、图像合成等实际应用,阐述了AI如何生成艺术作品。同时,文章指出未来发展中面临的版权、伦理等问题,强调理解这些算法对于探索艺术新境地的重要性。
18 3
|
6天前
|
机器学习/深度学习 人工智能 算法
详解AI作画算法原理
AI作画算法运用深度学习和生成对抗网络(GAN),通过学习大量艺术作品,模拟艺术家风格。卷积神经网络(CNN)提取图像特征,GAN中的生成器和判别器通过对抗训练生成艺术图像。循环神经网络和注意力机制可提升作品质量。这种技术开创了艺术创作新途径。
|
7天前
|
算法 数据可视化
【视频】Copula算法原理和R语言股市收益率相依性可视化分析
【视频】Copula算法原理和R语言股市收益率相依性可视化分析
12 0
|
7天前
|
机器学习/深度学习 自然语言处理 算法
【视频】K近邻KNN算法原理与R语言结合新冠疫情对股票价格预测|数据分享(下)
【视频】K近邻KNN算法原理与R语言结合新冠疫情对股票价格预测|数据分享
13 0