力扣刷题(399. 除法求值)floyd算法

399. 除法求值 - 力扣(LeetCode)

这种题目中给到是有向向量的题目,基本就要想到图的思想。

一旦路径中有了数值(权值),就要想到最小路径相关的算法,其中floyd算法就是用来求最小路径的。

floyd算法:需要两个矩阵,矩阵D是存放初始化某个节点到另一个节点最小权值,矩阵P用来存放一个节点到另一个节点的走法。然后就是去求解最短路径的矩阵,需要三层for循环,第一层是中转点k,第二层是路径的起始点v,第三层是路径的终点w。在操作的过程种不断的去对比直接从v走到w和从v到k再到w哪一个更快一些,更新更快的数据(包括权值,和P矩阵中的中转值)。

对于本题而言,难点在于D矩阵的创建,首先需要遍历一遍数组来获得所有的元素的个数vals_num,并用一个hashmap来存贮每一个节点对应的序号。然后再去创建矩阵D,遍历一遍数组,然后用map转换为序号,存放两个节点间权值,默认为-1。floyd操作的时候也需要修改,应该是判断D[v][k]和D[v][w]是否全大于0且D[v][w]小于0才去更新。

class Solution {

public:

    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {

        //首先通过一次遍历找出所有出现的节点的个数,然后利用这些节点去构成一个图

        int vals_num=0,n=equations.size();

        unordered_map<string,int> check;

        for(auto& k:equations)//通过一次遍历输入的数组,进行元素的编号,并统计元素的总个数

        {

            if(check.find(k[0])==check.end())check[k[0]]=vals_num++;

            if(check.find(k[1])==check.end())check[k[1]]=vals_num++;

        }

        //下面开始初始化权值矩阵D和最短路径矩阵P

        vector<vector<double>> D(vals_num,vector<double>(vals_num,-1.0));

        for(int i=0;i<n;++i)

        {

            int va=check[equations[i][0]],vb=check[equations[i][1]];//va和vb表示equations数组第i对

            D[va][va]=1.0;//自己除自己为1.0

            D[vb][vb]=1.0;

            //0和1元素对应元素序号

            D[va][vb]=values[i];

            D[vb][va]=1/values[i];

        }

        //通过floyd(弗洛伊德算法)模板,进行最小权值与最短路径的查找

        Floydfun(D);

        vector<double> ans;

        for(auto&k:queries)

        {

            int va=-1,vb=-1;

            if(check.find(k[0])!=check.end())va=check[k[0]];

            else {

                ans.push_back(-1.0);

                continue;

            }

            if(check.find(k[1])!=check.end())vb=check[k[1]];

            else{

                ans.push_back(-1.0);

                continue;

            }

            ans.push_back(D[va][vb]<0?-1.0:D[va][vb]);

        }        

        return ans;

    }

private:

    void Floydfun(vector<vector<double>>& D)

    {

        int n=D.size();

        for(int k=0;k<n;++k)//中转点

        {

            for(int v=0;v<n;++v)//路径起始点

            {

                for(int w=0;w<n;++w)//路径的终止点

                {

                    if(D[v][w]<0&&(D[v][k]>0&&D[k][v]>0))

                    {

                        D[v][w]=D[v][k]*D[k][w];//将权值更新为最小权值

                    }

                }

            }

        }

    }

};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yanzhe1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值