递归与算法优化实战解析

42、使用递归编写一个函数,该函数接受一个数字数组,并返回一个仅包含偶数的新数组。

def select_even(array)
  return [] if array.empty?
  if array[0].even?
    return [array[0]] + select_even(array[1, array.length - 1])
  else
    return select_even(array[1, array.length - 1])
  end
end

43、有一个名为“三角数”的数字序列。该序列从 1、3、6、10、15、21 开始,序列中的第 N 个数是 N 加上前一个数。例如,序列中的第 7 个数是 28,因为它是 7(即 N)加上 21(序列中的前一个数)。编写一个函数,该函数接受一个数字 N 并返回序列中对应的数字。也就是说,如果给该函数传入数字 7,函数将返回 28。

以下是实现该功能的函数:

def triangle(n):
    return 1 if n == 1 else n + triangle(n - 1)

44、这就是所谓的“唯一路径”问题:假设有一个由行和列组成的网格。编写一个函数,该函数接受行数和列数作为参数,并计算从网格左上角方格到右下角方格的所有可能的“最短”路径的数量。所谓“最短”路径,是指每一步要么向右移动一格,要么向下移动一格。函数应该计算出最短路径的数量。

以下是解决该问题的 Ruby 代码:

def unique_paths(rows, columns)
  return 1 if rows == 1 || columns == 1
  return unique_paths(rows - 1, columns) + unique_paths(rows, columns - 1)
end

45、下面的函数接受一个数字数组并返回数组元素的和,条件是某个特定数字不会使总和超过100。如果加上某个特定数字会使总和超过100,则忽略该数字。但是,这个函数会进行不必要的递归调用。修复代码以消除不必要的递归:

def add_until_100(array)
return 0 if array.length == 0
if array[0] + add_until_100(array[1, array.length - 1]) > 100
return add_until_100(array[1, array.length - 1])
else
return array[0] + add_until_100(array[1, array.length - 1])
end
end
为消除不必要的递归,可先计算剩余数组的和,再判断是否加上当前元素。修复后的代码如下:

def add_until_100(array)
  return 0 if array.length == 0
  remaining_sum = add_until_100(array[1, array.length - 1])
  if array[0] + remaining_sum > 100
    return remaining_sum
  else
    return array[0] + remaining_sum
  end
end

46、以下函数使用递归计算被称为“哥隆布数列”的数学序列中的第N个数。不过,它的效率非常低!使用记忆化方法对其进行优化。(做这个练习时,你实际上不需要理解哥隆布数列是如何运作的。)

可以创建一个哈希表来存储已经计算过的结果,避免重复计算,优化后的代码如下:

def golomb(n, memo = {}):
    if n == 1:
        return 1
    if n not in memo:
        memo[n] = 1 + golomb(n - golomb(golomb(n - 1), memo), memo)
    return memo[n]

47、在“不同路径”问题中,给定一个函数用于计算从网格左上角到右下角的不同路径数量,原函数代码如下:

def unique_paths(rows, columns)
return 1 if rows == 1 || columns == 1
return unique_paths(rows - 1, columns) + unique_paths(rows, columns - 1)
end
该函数未使用记忆化方法,效率较低。请使用记忆化方法来提高其效率。
为了实现记忆化,我们需要用行数和列数创建一个键。可以用一个简单的数组 [rows, columns] 作为键,优化后的代码如下:

def unique_paths(rows, columns, memo={})
  return 1 if rows == 1 || columns == 1
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值