关于本帖初衷
“一行”在程序员圈子,对于使用不同语言的 promgrammer 来说确实相对来说属于较敏感词。 不过也确实没想到有部分人反应会这么强烈,为了喷而喷,喷不到点上。
在我看来像函数式编程的语言和支持部分函数式编程的语言,能够合理使用一行的写法就该使用一行的写法。 人家弄一个函数出来,就是为了把定义变量、循环语句、等等重复的工作省掉。
我分享这行代码的出发点是因为几个高阶函数在解决这个问题的应用场景很典型
-- 个人认为是个很好的学习或了解 zip, reduce 的场景,以及涉及到的 functools、和 operator 标准库等。
===
关于算法性能问题
我在做这道题的时候,确实没有考虑 time complexity 和 space complexity;因为一般写法的最优解真的太显而易见。 所以我是从 know higher order function,practice higher order function 的考虑来实现这道题的。
讨论区正如上一个附言所说,有部分人指出这行的代码缺陷,确实有指到真正的点上。 从结论来说,谢谢 @mind3x 的写法更新,time complexity 为 O(n) 的写法可以更新成这样:
def list_extend(l, tuple): l.extend(tuple) return l class Solution: def shuffle(self, nums: List[int], n: int) -> List[int]: return reduce(list_extend, zip(nums[:n], nums[n:]), [])
如果要写成一行,其实也没有 “强扭”:
def solution(nums, n): return reduce(lambda l, t: (l.append(t), l)[-1], zip(nums[:n], nums[n:], [])
不过这么写,由于 reduce 多了 initial 参数,理解起来要多花点力气,脱离原本发 functools.reduce(operator.add, zip(nums[:n], nums[n:])) 这一行的初衷。
关于性能分析,为什么是 $O(n^2)$ @gwy15 在评论区已经解释清楚了。
注意一下我在评论区说的
l = [1, 2] l.append(1)
与
l = [1, 2] l = l + [1]
的区别。
关于 python 内置类型等方面的使用在算法性能上的分析,这一点有兴趣的朋友可以从 《python 算法教程》一书中了解。其中有说道 list、set、dict 需要注意的地方。
$O(tuple.__add__)$ => $O(n)$ 会造成
reduce(tuple.__add__, <tuple iter>) => $O(reduce) * O(tuple.__add__)$ => $O(n^2)$
的性能问题确实是我在使用这个解法的时候没有去严格分析的。
我了解 tuple + tuple 的问题,不过看了题目 1<=n<=500,我确实没有细想去分析出 $O(n^2)$ 的缺陷。 审题会看一下 n 范围,我想刷过上百道 leetcode 题的朋友应该会懂,这是个刷出来的习惯。因此我个人潜意识里面知道 tuple + tuple 会拖慢速度,但是由于取值范围小,没有去分析是 $O(n)$ 的慢还是 $O(n^2)$ 的慢。
$O(n)$ 写成 $O(n^2)$ 肯定是不好的,正如评论区某个人说的面试这么写是要被挂掉的。