Python代码通过递归查找最大值

如何解决Python代码通过递归查找最大值

我对在列表中找到最大值的Python代码有疑问。功能代码如下:

def large(x):
    if len(x) == 1:
        return x.pop(0)
    else:
        temp = x.pop(0)
        previous = large(x)
        if previous >= temp:
            return previous
        else:
            return temp

但是在此之前,我尝试过:

def large(x):
    if len(x) == 1:
        return x.pop(0)
    else:
        temp = x.pop(0)
        if large(x) >= temp:
            return large(x)
        else:
            return temp

它将返回错误消息为:

<ipython-input-74-dd8676a7c4e6> in large(x)
      3         return x.pop(0)
      4     else:
----> 5         temp = x.pop(0)
      6         if large(x) >= temp:
      7             return large(x)

IndexError: pop from empty list

玩具数据为:

inputlist = [6,1,3,2,4,5,6]
large(inputlist)

谢谢您的帮助。我找不到此错误的主要原因。对于我来说,这两个代码是完全相同的。

解决方法

问题

if large(x) >= temp:
    return large(x)

是您最终多次调用large(x)(因此也叫pop),这会从列表中删除元素。

就个人而言,我会比使用pop之类的变异函数更喜欢这种样式。

def large(x):
    if len(x) == 1:
        return x[0]
    remainder = large(x[1:])
    return x[0] if x[0] > remainder else remainder
,

与OneCricketeer相同的解决方案 但不必在每次递归调用时都无需创建列表切片。 它还处理一个空列表。

def large(x):
    def rec(y):
        try:
            v = next(y)
        except StopIteration:
            return None
        r = rec(y)
        if r is None:
           return v
        return v if v > r else r
    return rec(iter(x))

inputlist = [6,1,3,2,4,5,6]
print(large(inputlist))
print(large([]))

产生

6
None
,

这不能回答为什么原件不正确。相反,它奠定了可用于实现许多递归问题的“标准模式”。

我想知道应该如何用索引而不是弹出来消除每一轮中的元素数量?

不要“消除”这些元素:-)

许多递归友好问题通过减小每个步骤的 range 而起作用。这包括查找最大值(或任何可以表示为折叠的操作),二进制搜索,自上而下的合并排序等。许多这些问题本身都是使用数组和子问题归约的伪代码表示的通过调整每个递归调用的范围。在进行max / binary搜索时,这还可以避免对原始对象进行任何变异。

因此,递归max函数可以编写如下。请注意,这种通过工作状态的形式是尾叫友好的。尽管我发现这种形式更容易表达某些问题,但在Python中,[C]Python does not support Tail-Call Optimizations ^ 并不重要。

def my_max(lst,m=None,i=0):
  # base-case: return result of work
  if len(lst) == i:
    return m
  # Compute max through here
  c = lst[i]
  m = c if m is None or c > m else m
  # Call recursive function increasing the index by 1.
  # This is how the problem advances.
  return my_max(lst,m,i + 1)

上面的示例还使用默认参数代替了辅助方法。这是一种使用递归结果的替代方法(通常是递归函数的引入方式)以及离散辅助方法。

def my_max(lst):
  # Wrapper can ensure helper pre-conditions.
  # In this case that is a non-Empty list per the base case check.
  if not lst:
    return None
  return my_max_helper(lst,0)

def my_max_helper(lst,i):
  # base case: last item in list returns itself
  if len(lst) - 1 == i:
    return lst[i]
  c = lst[i]
  m = my_max_helper(lst,i + 1)
  return c if c > m else m

在两种情况下,临时变量都用于避免重复的表达式;尽管有时只是一种样式选择,但由于避免了额外的pop-mutation的意外副作用,这种一致性本来可以缓解原始问题。

应使用list或支持O(1)索引查找的其他序列调用上述方法 特别是,“索引”方法不适合并且不能与生成器对象一起使用。还有其他答案可以解决这个问题-请当心避免使用诸如h,*t=ll[1:]之类的潜在列表片段,这些片段可能导致不良的性能范围。

^ Python中有一些模块可以通过跳板模拟 TCO。

,

由于这是递归练习,而不是我们在系统代码中要做的事情,因此,我将使用描述性代码而不是高效代码来做类似的事情:

def largest(array):
    if array:
        head,*tail = array

        if tail and head < (result := largest(tail)):
            return result

        return head

    return None

if __name__ == "__main__":
    from random import choices

    array = choices(range(100),k=10)

    print(array,'->',largest(array))

输出

> python3 test.py
[46,67,22,23,20,30,7,87,50] -> 87
> python3 test.py
[83,77,61,53,65,68,43,44,47] -> 83
> python3 test.py
[36,99,47,93,60,56,90,44] -> 99
> 

如果您确实需要有效,我建议安全这样做。具体来说,请不要公开带有特殊参数的API,以表明调用者没有使用 调用方,例如:

def my_max(lst,i=0):

因为它们可以为这些额外的参数提供值,这会使您的代码失败,并最终将其归咎于您。公开了调用者可能调用的内部函数的功能,而不是预期的功能:

def my_max(lst,i=0):

def my_max_helper(lst,i):

偶然为虚名my_max_helper()自变量调用i。相反,我会考虑嵌套您的函数以避免此类调用错误:

def largest(array):

    def largest_recursive(array,index):
        a = array[index]

        if len(array) - index != 1:
            if (b := largest_recursive(array,index + 1)) > a:
                return b

        return a

    if array:
        return largest_recursive(array,0)

    return None

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-