【问题标题】:how should I order my statement in a short circuit and?我应该如何在短路时订购我的陈述?
【发布时间】:2016-01-12 21:21:06
【问题描述】:

嗯,我正在做一个question on leetcode to verify if something is a symmetric tree,我有这行代码:

if A.val == B.val and Issymmetric(A.left, B.right) and Issymmetric(A.right,B.left):
    return True

基本上如果A的根值与B的根值相同,并且A的左子树与B的右子树对称,再加上A的右子树与B的左子树对称,那么我得出结论A,B是对称的

但是这段代码运行很慢:在 leetcode 上 80ms 但是如果我将 if 语句的顺序更改为:

if Issymmetric(A.left, B.right) and Issymmetric(A.right,B.left) and A.val == B.val:
    return True

这段代码具有相同的逻辑,但只需要 52ms,我有点假设应该在彻底处理整个左/右子树之前比较根值(通常这更有效,它可能会节省大量的递归调用)

TL;DR 这给我的印象是python以相反的顺序评估短路和,所以我对我的本地环境做了一点测试:

def f1():
   print 1
   return True
def f2():
   print 2
   return True
if f1() and f2():
   pass
# but the output I got is 1,2...

我很困惑,如果短路的顺序是从左到右,为什么我的代码之间会有巨大的性能差异?

如有必要,我可以上传整个 IsSymmetric() 函数 我做了一些进一步的测试,我认为 80ms 只是 leetcode 的一个小故障,谢谢

【问题讨论】:

  • 为什么你会认为它是反过来的?如果 == 需要 28 毫秒,而 ISsymmetric 分别需要 52 毫秒,那么您得到的结果对于从左到右的短路评估是有意义的。
  • 输入是什么样的?如果树的根节点非常相似并且仅在树的末端有所不同,那么这就是您的代码会变慢的原因。这就像问为什么当列表的最后一个元素不同时,检查列表是否相等的方法很慢。
  • 它做了一些测试,80ms 在 leetcode 上看起来像是一次性的……现在恢复正常了,我应该删除这篇文章吗?

标签: python recursion short-circuiting


【解决方案1】:

这是一个有趣的问题,涉及到一些微妙的领域。

在查看条件以及条件的速度时,您需要查看它的辨别力。即,它是否立即给出“正确”答案,或者您是否需要继续查看其他条件。

最好先有一个缓慢但有区别的条件,这取决于许多因素。

考虑两个函数:

def f1(c):
    sleep(20)
    return (c % 2) == 0

def f2(c):
    sleep(25)
    return (c % 4) == 0

f1() 速度很快,但辨别力不是很强,而f2() 速度较慢,但​​辨别力更强。考虑f1(c) and f2(c)f2(c) and f1(c) 两个表达式c in 0..3

=== ===== ====
c   exp1  exp2
=== ===== ====
0   20+25 25+20
1   20+0  25+0
2   20+25 25+0
3   20+0  25+0
=== ===== ====
    130   120

请注意,首先使用slow 条件会导致(稍微)更短的总时间。

【讨论】:

  • 有趣的是,递归函数确实更有可能失败,因为它比较整个子树而不是只比较一个节点,我猜如果不一致(导致非对称的节点)很深(靠近叶子),这是有道理的...我在 leetcode 上提交了相同的代码,现在显示 52 毫秒...我想我永远不会知道它是输入还是他们网站上的缓存问题
【解决方案2】:

Python if 语句将在第一次出现虚假迹象时中断。 IE。

if a == True and b == True:

如果 a 为 False,将中断,并且仅在 a 为 True 时评估 b

因此,如果您有一系列比较,就像您一样,并且想要优化速度,请将您最常见的情况放在首位。

【讨论】:

  • 你是说我应该在左右子树上做 IsSymmetric(),然后做A.val == B.val,但我在想即使左右子树确实是对称的,如果A.val != B.val,那么我们只是在浪费递归,我的逻辑错了吗?
  • 我的意思是,如果您的逻辑中最常见的breakIssymmetric(A.left, B.right),那么它应该在其余部分之前。但是,只有在正确分析代码、确定结果、甚至关心性能优化后,才能进行这种类型的优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多