【问题标题】:Why might a recursive solution have a much more complicated base case than a DP solution?为什么递归解决方案的基本情况可能比 DP 解决方案复杂得多?
【发布时间】:2016-12-15 14:15:18
【问题描述】:

我正在研究一个算法问题,以找到将整数解码为字符串的多种方法。我已经制定了一个 DP 解决方案和递归解决方案。

递归解决方案似乎有一个更复杂的基本情况。我试图理解为什么会这样,以及它是否是一种模式,或者我是否真的不擅长编写递归基本案例。

DP解决方案:

# @param {String} s
# @return {Integer}
def num_decodings(s)
  return 0 if s.length == 0
  n = s.length
  memo = Array.new(n+1,0)
  memo[n] = 1
  memo[n-1] = s[n-1]=="0" ? 0 : 1
  (0...n-1).to_a.reverse.each do |i|
    next if s[i] == "0"
    memo[i] = s[i...(i+2)].to_i <= 26 ? memo[i+1] + memo[i+2] : memo[i+1]
  end
  puts memo.to_s
  return memo[0]
end

递归解法:

# @param {String} s
# @return {Integer}
def num_decodings(s)
    #puts "s: #{s}"
    return 0 if s.length == 0
    return 0 if s[0] == "0"
    return 1 if s.length == 1
    return 1 if s.length == 2 && s[1] == "0" && s.to_i <= 26
    return 0 if s.length == 2 && s[1] == "0" && s.to_i > 26
    return 2 if s.length == 2 && s.to_i <= 26
    return 1 if s.length == 2
    @ways ||= {}
    return @ways[s] if @ways[s]
    if s[0..1].to_i <= 26 
        @ways[s] = num_decodings(s[1..-1]) + num_decodings(s[2..-1])
    else
        @ways[s] = num_decodings(s[1..-1])
    end
    #puts @ways
    return @ways[s]
end

输入:"2545632102" 输出:2

Leetcode 上的这个问题:https://leetcode.com/problems/decode-ways/

【问题讨论】:

    标签: algorithm recursion dynamic-programming


    【解决方案1】:

    我继续研究递归解决方案,并意识到虽然 DP 解决方案只需要考虑 n-1 和 n-2,但我的递归基本情况恰好是不必要的奇怪。所以我简化了它并最终得到了这个:

    def num_decodings(s)
        return 0 if s.length == 0
        return 0 if s[0] == "0"
        return 1 if s.length == 1
        @ways ||= {}
        return @ways[s] if @ways[s]
        if s[0..1].to_i <= 26
            prev = s.length <= 2 ? 1 : num_decodings(s[2..-1])
            @ways[s] = num_decodings(s[1..-1]) + prev
        else
            @ways[s] = num_decodings(s[1..-1])
        end
        return @ways[s]
    end
    

    该解决方案已经与 DP 解决方案非常相似,并且具有相似的复杂程度。

    当然DP方案还是更快。

    【讨论】:

    • 对。您的原始代码具有笨拙的基本逻辑。一般来说,DP 解决方案应该与递归解决方案基本相同,只是增加了一个步骤:在递归之前,检查是否存储了上一次调用的结果。
    猜你喜欢
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 2014-08-20
    • 2020-08-09
    • 2017-01-30
    • 2013-07-22
    • 1970-01-01
    相关资源
    最近更新 更多