LeetCode 399 除法求值

把它想象成一个走路的问题,问题的两个分别是路的两端,要找到各个子路径把这条路连起来,要求各个子路径头尾相连。顺着这个思路想,队列?回溯?动态规划?发现题目确实存在子状态,即每一条路径都可以划分为子路径的乘积。

这一次为了方便使用,定义二维数组dp,dp[i][j]表示从节点i到节点j的路径长度。

1、构建letter map[string]int,dp [][]float64,res []float64

2、遍历equations,将不同的节点存储到map中并从0开始分配编号。同时初始化填充dp,将equations 中已有的子路径填充到dp中(主义针对equations中的每一个二元组,可以填充两个子路径),在遍历的过程中,如果发现当前节点已经存储于letter中,那么dp中存在可扩充的路径,对其进行补充(例如,已经遍历过[a, b]后,再次遍历到[b, c],发现b已经在letter中,那么就找到以b为起始的子路径,将其扩充为 [c,b]+[b,a]=[c,a],以及直接反转后的[a,c])。

3、遍历queries,针对其中每一个问题的开始节点,首先判断节点是否在letter中:

  • 如果不在,直接将-1.00存储到res中并继续遍历下一个问题。
  • 如果存在,判断该路径是否已经在dp中,如果是,将对应的值存储到res中,继续遍历下一个问题,如果不是,存储-1.00到res中。

按照上述思路完成代码编写后发现存在问题(给的三个测试用例过了,但是提交出了问题)问题如下,例如已知[a,b][c,e][b,c],按照上述代码的思路,dp中的路径更新顺序为(1)dp[a][b],dp[b][a](2)dp[c][e],dp[e][c](3)dp[b][c],dp[c][b],dp[a][c],dp[c][a],这样的更新顺序缺失了 dp[a][e],dp[e][a]的可能。

针对这一个问题,想到了两种解决的思路 1)BFS:每当产生新的产生式,例如上述(3)中出现了新的 dp[a][c],dp[c][a],就将新的[a,c]组合加入到 equations 中,同步更新 values(这样一想发现我这种遍历完所有可能的组合的情况反而是绕远了,不如直接从queries 出发,BFS遍历所有可能的组合,找到可能的值)。2)递归:这次从 queries 出发,遍历以当前字母为开头的多有可能,将长串逐步划分为短的子串相乘。

决定实现 2)了,练练递归,而且1)感觉思路跟递归差不多但会没有那么顺畅

func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 {
    var res []float64
    var letter map[string]int = make(map[string]int)
    var queue [][]int
    var ma [][]float64=make([][]float64, 2*len(equations))
    for i:=0; i<len(ma); i++{ ma[i]=make([]float64, 2*len(equations)) }
    
    num:=0
    for k, e := range equations{
        if _, ok := letter[e[0]]; !ok { 
            letter[e[0]] = num
            num++ 
        }
        if _, ok := letter[e[1]]; !ok { 
            letter[e[1]] = num
            num++ 
        }
        queue=append(queue, []int{letter[e[0]], letter[e[1]]})
        ma[letter[e[0]]][letter[e[1]]]=values[k]
        ma[letter[e[1]]][letter[e[0]]]=1/values[k]
    }
    // fmt.Println(ma)
    var helper func(s, e int, visited map[int]bool) float64
    helper = func(s, e int, visited map[int]bool) float64 {
        // fmt.Println(s, e)
        if ma[s][e]!=0.0 { return ma[s][e] }
        for i:=0; i<num; i++{
            if _, ok:=visited[i]; !ok && ma[s][i]!=0.0{
                visited[i]=true
                t:=helper(i, e, visited)
                if t>0{ return ma[s][i]*t }
            }
        }
        return -1
    }

    for _, q:=range(queries){
        v0, ok0 := letter[q[0]]
        v1, ok1 := letter[q[1]]
        if !ok0 || !ok1{
            res=append(res, -1.0)
        }else{
            res=append(res, helper(v0, v1, make(map[int]bool)))
        }
    }
    return res
}

LeetCode热题100完结撒花🎉

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据引用\[1\],可以使用暴力解法来求解滑动窗口的最大值。具体的做法是,遍历数组,对于每个窗口,使用一个内部循环来找到窗口中的最大值,并将其存储在结果数组中。时间复杂度为O(n*k),其中n为数组长度,k为窗口大小。 根据引用\[2\],还可以使用队列来求解滑动窗口的最大值。具体的做法是,使用一个双端队列来维护一个单调递减的窗口。遍历数组,对于每个元素,首先判断队头是否在滑动窗口范围内,如果不在,则将其从队头移除。然后,将当前元素与队尾元素比较,如果当前元素大于队尾元素,则将队尾元素移除,直到队列为空或者当前元素小于等于队尾元素。最后,将当前元素的索引插入队尾。如果滑动窗口的元素个数达到了k个,并且始终维持在窗口中,就将队头元素加入答案数组中。时间复杂度为O(n),其中n为数组长度。 综上所述,可以使用暴力解法或者使用队列来求解leetcode滑动窗口的最大值。 #### 引用[.reference_title] - *1* *3* [leetcode239. 滑动窗口最大值](https://blog.csdn.net/kkkkuuga/article/details/124829581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode#239. 滑动窗口最大值 (Java解法)](https://blog.csdn.net/paranior/article/details/114890555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值