[一起来刷leetcode吧][11]--No.399 Redundant Connection

本文解析了LeetCode上的第399题——Redundant Connection的算法实现,介绍了如何通过构建图模型解决变量间比例关系查询的问题,并提供了一段详细的Python代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章是程序自动发表的,详情可以见 这里
href="http://ounix1xcw.bkt.clouddn.com/github.markdown.css" rel="stylesheet">

这是leetcode的第399题--Redundant Connection

  题目 Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.

Example: Given a / b = 2.0, b / c = 3.0. queries are:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? . return [6.0, 0.5, -1.0, 1.0, -1.0 ].

The input is: vector > equations, vector & values, vector > queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector .

According to the example above:

    equations = [ ["a", "b"], ["b", "c"] ],
    values = [2.0, 3.0],
    queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].

The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.   思路 这道题由于是除法,会想到有向图,但是发现,a->b, c->b有可以推出a,b关系,所以连通即可。为了能方便搜索,我又增加了一条反向边vuy(代码第161行),当然权值为倒数,可是这样增加了深搜难度,于是要解决环的搜索问题(代码第127行)   

show me the code

from collections import Iterable,deque
class vertex:
    def __init__(self,mark,val=None ,firstEdge = None):
        self.mark = mark
        self.val = val
        self.firstEdge = firstEdge
        self.isVisited = False
    def __str__(self):
        if '0'<=self.mark[0]<='9':return 'v' str(self.mark)
        return str(self.mark)
    def __repr__(self):
        li=[]
        arc= self.firstEdge
        while arc!=None:
            li.append(arc)
            arc= arc.outNextEdge
        return str(self)  '  to:' str([str(i.inArrow) for i in li])
class edge:
    def __init__(self,outArrow,inArrow,outNextEdge = None,inNextEdge = None, weight = 1): 
        self.weight = weight
        self.inNextEdge = inNextEdge 
        self.outNextEdge = outNextEdge
        self.outArrow = outArrow
        self.inArrow=inArrow
        self.isVisited = False
    def __str__(self):
        return '--' str(self.weight) '-->'
    def __repr__(self):
        return str(self)
class graph:
    def __init__(self): 
        self.vertexs = {}
        self.edges = {}
    def __getitem__(self,i): 
        return self.vertexs[i]
    def __setitem__(selfi,x):
        self.vertexs[i]= x
    def __iter__(self):
        return iter(self.vertexs.values())
    def __bool__(self):
        return len(self.vertexs)!=0
    def addVertex(self,vertexs):
        '''vertexs is a iterable or just a mark that marks the vertex,whichc can be every imutable type'''
        if not isinstance(vertexs,Iterable):vertexs=[vertexs]
        for i in vertexs:
            if  not isinstance(i,vertex) and  i not in self.vertexs:self.vertexs[i]= vertex(i)
            if isinstance(i,vertex) and  i not in self.vertexs:self.vertexs[i.mark]= i
    def isConnected(self,v,u):
        v = self.__getVertex(v)
        u = self.__getVertex(u)
        arc= v.firstEdge
        while arc!=None:
            if arc.inArrow==u:return True
            arc = arc.inNextEdge
        return False
    def __getVertex(self,v):
        if not isinstance(v,vertex):
            if v not in self.vertexs:
                self.vertexs[v]=vertex(v)
            return self.vertexs[v]
        return v
    def addEdge(self,v,u,weight = 1):
        v = self.__getVertex(v)
        u = self.__getVertex(u)
        arc = v.firstEdge
        while arc!=None:         #examine that if v,u have been already connected
            if arc.inArrow==u: return
            arc= arc.outNextEdge
        newEdge = edge(v,u,v.firstEdge,u.firstEdge,weight)
        self.edges[(v.mark,u.mark)] = newEdge
        v.firstEdge = newEdge
    def delEdge(self,v,u):
        if not isinstance(v,vertex):v= self.vertexs[v]
        if not isinstance(u,vertex):u= self.vertexs[u]
        self._unrelated(v,u)
        del self.edges[(v.mark,u.mark)]
    def _unrelated(self,v,u):
        if v.firstEdge==None:return 
        if v.firstEdge.inArrow == u:
            v.firstEdge =v.firstEdge.outNextEdge
        else:
            arc = v.firstEdge
            while arc.outNextEdge!=None:
                 if arc.outNextEdge.inArrow ==u:
                     arc.outNextEdge = arc.outNextEdge.outNextEdge
                     break
    def revisit(self):
        for i in self.vertexs:
            self.vertexs[i].isVisited=False
        for i in self.edges:
            self.edges[i].isVisited=False
    def __str__(self):
        arcs= list(self.edges.keys())
        arcs=[str(i[0]) '--->' str(i[1]) '  weight:' str(self.edges[i].weight) for i in arcs]
        s= '\n'.join(arcs)
        return s
    def __repr__(self):
        return str(self)
    def notIn(self,v):
        if (isinstance(v,vertex) and  v.mark not in self.vertexs) or v not in self.vertexs:
            return True
        return False
    def visitPath(self,v,u):
        '''bfs'''
        if self.notIn(v) or  self.notIn(u):
            return  None,None
        v = self.__getVertex(v)
        u = self.__getVertex(u)
        if v.firstEdge==None:return None,None
        q=deque([v.firstEdge])
        isFind=False
        vs,es=[],[]
        while len(q)!=0:
            vs,es=[],[]
            arc= q.popleft()
            if arc.outNextEdge!=None and not arc.outNextEdge.isVisited:q.append(arc.outNextEdge)
            while arc!=None:
                if arc.isVisited:break
                arc.isVisited=True
                es.append(arc)
                vs.append(arc.inArrow)
                arc.outArrow.isVisited=True
                if arc.inArrow==u:
                     isFind=True
                     break
                arc = arc.inArrow.firstEdge
                while arc.inArrow.isVisited and arc.outNextEdge:arc = arc.outNextEdge
            if isFind:break
        else:return None,None
        '''
        se = [str(i) for i in es]
        sv = [str(i)  for i in vs]
        print(str(v),end='')
        for i,j in zip(se,sv):
            print(i,j,end='')
        '''
        return vs,es
    def hasVertex(self,mark):
        return mark in self.vertexs
    def display(self):
        print('vertexs')
        for i in self.vertexs:
            print(self.vertexs[i].__repr__())
        print('edges')
        for i in self.edges:
            arc=self.edges[i]
            print(str(arc.outArrow) str(arc) str(arc.inArrow))

class Solution(object):
    def calcEquation(self, equations, values, queries):
        """
        :type equations: List[List[str]]
        :type values: List[float]
        :type queries: List[List[str]]
        :rtype: List[float]
        """
        rst =[]
        g= graph()
        for edge,wt in zip(equations,values):
            g.addEdge(edge[0],edge[1],wt)
            g.addEdge(edge[1],edge[0],1/wt)###### to serach quickly but sacrifacing some space
        g.display()
        for i in queries:
            if i[0]==i[1]:
                if i[0] in g.vertexs:rst.append(1.0)
                else:rst.append(-1.0)
                continue
            _,path = g.visitPath(i[0],i[1])
            if path==None:
                if not path:rst.append(-1.0)
            else:
                mul = 1
                for i in path:mul*=i.weight
                rst.append(mul)
            g.revisit()
        return rst
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值