【问题标题】:Coding Style in PythonPython 中的编码风格
【发布时间】:2014-03-10 07:16:05
【问题描述】:

我最近接受了一家著名的硅谷公司的采访。我被要求以 O(n) 的时间复杂度为以下问题编写代码。

问题:

编写一个给定整数数组的函数。如果它应该返回 true 任何值在数组中至少出现两次,如果它应该返回 false 每个元素都是不同的。

问题的关键是使用哈希映射。我用python写了以下代码:

def containsDuplicate(arr):
    hashi={}
    for i in arr:
        try:
            hashi[i]+=1
            return 1
        except KeyError:
            hashi[i]=1
    return 0

整体面试很顺利,我能够找出所有问题的最佳解决方案(有效的解决方案)。 后来我收到了公司的邮件,说我不是这个职位的最佳人选。当被问及拒绝的原因时,我被告知要改进我的编码风格。

当 HR 说我需要改进我的编码风格时,她是什么意思?编写上述问题的解决方案的最佳方法是什么?

编辑:

再次阅读代码后,我相信甚至没有必要这样做 hashi[i]+=1 。只需return 1 就足够了,但我不认为他们仅仅因为我的编码中的这个小错误而拒绝了我。

【问题讨论】:

    标签: python arrays python-2.7 coding-style hashmap


    【解决方案1】:

    这个问题的更简洁的解决方案是:

    def has_dups(arr):
        return len(set(arr)) != len(arr)
    

    在创建集合时,任何重复都将被删除,因此计数会告诉我们结果。我认为从迭代器创建集合是 O(n),所以它可以满足这个要求。

    虽然不能保证这就是他们正在寻找的东西!

    【讨论】:

    • 这将是正确的解决方案。请注意提供的所有其他解决方案要复杂得多。为了挑剔风格,我会完整地拼出单词。对我来说,如果你不这样做,你就不会理解集合,并且你在 Python 工具包中缺少一个基本工具。
    • 偷偷摸摸但可能很慢,因为它总是会处理所有事情,在面试时我会担心缺乏文档。
    • 我喜欢这个解决方案。但如果面试官的目标是判断算法能力,那么依赖集合类中现有的算法可能是不明智的......
    【解决方案2】:

    查看PEP-8

    from collections import defaultdict
    def is_duplicate(string):
        freq = defaultdict(lambda: 0)
        for c in string:
            freq[c] += 1
        return all(v == 1 for v in freq.values())
    

    【讨论】:

    【解决方案3】:

    你会使用“in”而不是 try 和 except。

    def containsDuplicate(arr):
        hashi={}
        res = 0    
        for i in arr:
            if i not in hashi:
               hashi[i]=1
            else:
                res = 1
                break
        return res
    

    【讨论】:

      【解决方案4】:

      可能是他们不喜欢您返回 0 或 1 而不是 False 或 True 的事实。

      【讨论】:

      • 我还建议在面试中提供带有 no cmets 或 docstrings 的代码并依赖异常作为代码的一部分都是 bad想法。实际上,它们一直都是坏主意!
      【解决方案5】:

      尝试对面试拒绝原因进行逆向工程通常是一项困难且通常毫无意义的练习,因此让我们将问题改造成更有趣的内容,并继续改进你的答案,就像给你更多时间一样。

      编写一个给定整数数组的函数。如果任何值在数组中至少出现两次,它应该返回 true,如果每个元素都是不同的,它应该返回 false。

      def containsDuplicate(arr):
          hashi={}
          for i in arr:
              try:
                  hashi[i]+=1
                  return 1
              except KeyError:
                  hashi[i]=1
          return 0
      

      好吧,python 有一个style guide,它暗示了一些spacing,所以让我们这样做。 (没有人会因此拒绝某人,顺便说一句)

      Python 还使用 TrueFalse,而不是 C 风格的 0 和 1 来表示布尔值。

      def containsDuplicate(arr):
          hashi = {}
          for i in arr:
              try:
                  return True
              except KeyError:
                  hashi[i] = 1
          return False
      

      现在,Python 正式订阅了EAFP,您在其中使用异常而不是检查,但有些人不同意。如果您使用检查,我们有:

      def containsDuplicate(arr):
          hashi = {}
          for i in arr:
              if i in hashi:
                  return True
              else:
                  hashi[i] = True
          return False
      

      但是,是时候变聪明了。使用集合,我们可以做到:

      def containsDuplicate(a):
          return len(set(a)) != len(a)
      

      【讨论】:

      • 边栏:如果我是面试官,有人给了我一套解决方案,我会和他们一起玩,让他们证明这是最好的解决方案。他们可以:认为这是一个基于了解 python 内部的 O(n) 解决方案,或者他们可以告诉我这是最简单的维护代码。任何一个我都可以。
      • 我真的不认为使用集合是“变得聪明”。这是最简单直接的方法。
      • 同意。如果你熟悉它,它很简单,它是 O(n)(假设 python 内部按我期望的方式工作)并且很容易阅读/维护。但是,如果之前没见过,面试的时候是不可能当场拿出来的……
      • 这使它成为一个很好的面试问题,因为winging-这并不是公司雇用的真正技能。
      • @AaronHall :虽然我以前用过套装,但在采访时似乎并没有给我留下深刻印象。所以我猜除了集合的应用外,面试官可能会寻找你正在遵循的其他方法来编写代码。
      【解决方案6】:

      这里有一些建议。

      from collections import defaultdict
      
      def contains_duplicates(arr): # PEP recommends not using camel case
          arr_count = defaultdict(lambda: 0) # you should use defaultdict to specify a default value
          for i in arr:
              arr_count[i] += 1
              if arr_count[i] >= 2:
                  return True # Python has a boolean type; you shouldn't use 0s and 1s
          return False
      

      【讨论】:

      • 您可以使用int 而不是lambda: 0。也许不那么明显。
      • @detly:你能详细说明一下吗?
      • @detly :我不知道可以在不使用 lambda 的情况下将 defaultdict 初始化为零。感谢您的信息。
      • @JayanthKoushik - 如果您只是调用int(),则默认为0。因此,您可以将int 作为defaultdict 用于其默认值的可调用事物传递,以获取所有默认值的0
      【解决方案7】:

      关于您的风格,您似乎不知道集合的实现方式与 Python 中的 dicts 类似,而且您的代码不必要地复杂。我会像 Gavin H 那样实现它。

      此外,您应该处理的其他样式元素(参见 PEP8):

      • 赋值运算符周围的单个空格
      • 使用下划线来分隔名称中的单词,而不是驼峰式
      • 学习 dict 方法(您可以使用 dict.get 方法而不是 try/except)
      • 返回 True 或 False,而不是 1 或 0

      【讨论】:

        【解决方案8】:

        您的代码存在许多编码风格问题,但我最不喜欢的一个是即使前两个元素相同,它也会始终处理整个数组。

        我对此的看法如下,它可能不是最短的,但以后再回去会更好:

        def has_dups(array):
            """ Return true if there are any duplicates in the array """
            result = False  # Return value
            seen = {}  # Dictionary of values seen
            for val in array:
                if seen.get(val, False):
                    result = True  # We have a duplicate
                    break  # Return NOW
                else:
                    seen[val] = True # Add to seen
             return result
        

        在商业组织中,您通常会寻找符合以下条件的代码:

        1. 符合规范 - 你的不符合,因为它返回 0/1 而不是 False/True
        2. 符合标准 - 你的有几个 PEP8 问题
        3. 清晰且可维护 - 您的代码缺少 cmets 并依赖异常来节省面试时间,最好至少标记您要评论代码的位置。
        4. 是可测试的 - 这意味着一个入口和出口和低复杂度

        编辑

        OP 指出他们的代码在我错过的第一个非异常上返回 - 这强调了上面的第 3 点和第 4 点。

        【讨论】:

        • 如果前两个元素与我在try 语句中编写的return 1 相同,它将不会处理整个数组。
        • 错过了这就是为什么在商业环境中不赞成多次退货声明的原因。其他人可能必须维护您的代码。
        • 我刚刚做到了!如果这对我有帮助的话,那家机构给我回电话说——他们喜欢你的技术能力和个性,但拒绝了你的穿着——你到底穿了什么?我的回答是黑色和白色以外的颜色,每个人都穿着黑色裤子,白色衬衫,黑色领带......
        • 哈哈 .. 我想对他们来说,外表比个人的技能更重要。
        【解决方案9】:

        在这个版本中,我试图让提前回归显而易见。

        def contains_duplicates(arr):
            # returns True if a value of arr occurs more than once
            hashi = {}
            for i in arr:
                if i in hashi:
                    return True
                hashi[i] = 1
            return False
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-02-18
          • 2010-10-03
          • 1970-01-01
          • 1970-01-01
          • 2015-09-26
          • 1970-01-01
          • 2016-03-21
          相关资源
          最近更新 更多