【问题标题】:Python: Find longest binary gap in binary representation of an integer numberPython:在整数的二进制表示中查找最长的二进制间隙
【发布时间】:2018-08-03 17:32:02
【问题描述】:

我想知道我的实施是否有效。 我试图使用 python 找到该问题的最简单和低复杂度的解决方案。

def count_gap(x):
    """
        Perform Find the longest sequence of zeros between ones "gap" in binary representation of an integer

        Parameters
        ----------
        x : int
            input integer value

        Returns
        ----------
        max_gap : int
            the maximum gap length

    """
    try:
        # Convert int to binary
        b = "{0:b}".format(x)
        # Iterate from right to lift 
        # Start detecting gaps after fist "one"
        for i,j in enumerate(b[::-1]):
            if int(j) == 1:
                max_gap = max([len(i) for i in b[::-1][i:].split('1') if i])
                break
    except ValueError:
        print("Oops! no gap found")
        max_gap = 0
    return max_gap

让我知道你的意见。

【问题讨论】:

  • codility BinaryGap test 允许使用 18 种不同语言编写解决方案:C, C++, C#, Go, Java 8, Java 11, JavaScript, Kotlin, Lua, Objective-C, Pascal, PHP, Perl, Python, Ruby, Scala, Swift 4, Visual Basic。所以我认为没有任何理由将此问题仅限于 Python。

标签: python python-3.x binary


【解决方案1】:

我确实意识到简洁并不意味着可读性或效率。

但是,能够立即用口语阐明解决方案并在 Python 中实现它,这构成了我对时间的有效利用。

对于二进制间隙:嘿,让我们将 int 转换为二进制,去除尾随零,在 '1' 处拆分为列表,然后在列表中找到最长的元素并获取该元素的长度。

def binary_gap(N):
    return len(max(format(N, 'b').strip('0').split('1')))  

【讨论】:

  • 超级好看:thumbsup:
  • 这一班轮确实非常高效。但是我卡在了一个点上,strip 的功能是什么?我在不使用条带的情况下运行了该代码,它具有相同的输出。提前谢谢你。
  • 根据定义,二进制间隙是“1 之间的零”,因此不应将尾随零视为二进制间隙。尝试使用 int 32(二进制为 100000)运行这两个版本。使用条带你得到 0(没有二进制间隙)没有条带你得到 5(这是不正确的,因为 1 之间没有 5 个零)。
  • 如果您正在寻找性能:@Orenico 在他的答案中使用的 bin() 比 format(N, 'b') 快很多。
  • @quassy - 请定义“快一点”。使用 timeit 和 Python 3.8 进行的随意检查表明 format() 比 bin()[2:] 快一点。同样的随意检查也表明可以声称f"{N:b}"“快得多”。
【解决方案2】:

您的实现将整数转换为以二为底的字符串,然后访问字符串中的每个字符。相反,您可以使用<<& 访问整数中的每一位。这样做将避免访问每个位两次(首先将其转换为字符串,然后检查结果字符串中是否为“1”)。它还将避免为字符串分配内存,然后为您检查的每个子字符串分配内存。

您可以通过访问 1

例如:

def max_gap(x):
    max_gap_length = 0
    current_gap_length = 0
    for i in range(x.bit_length()):
        if x & (1 << i):
            # Set, any gap is over.
            if current_gap_length > max_gap_length:
                max_gap_length = current_gap_length
            current_gap_length = 0
         else:
            # Not set, the gap widens.
            current_gap_length += 1
    # Gap might end at the end.
    if current_gap_length > max_gap_length:
        max_gap_length = current_gap_length
    return max_gap_length

【讨论】:

  • 我建议使用int.bit_length 方法而不是ceil(log2(...)) 计算,以避免由于舍入导致的极端情况错误。
  • 您说过您的实现将整数转换为以二为底的字符串,然后访问字符串中的每个字符,但这并不完全正确,因为我在检测到一个字符后中断然后我拆分。请您强调一下为什么您的实现在时间和内存复杂性方面应该更好。
  • 你仍然需要访问每个角色。不然split怎么能找到合适的分割位置?它会访问每个字符,直到找到您提供的值。
  • 嗨,Jean,您的代码比我提供的要慢得多。我将在答案中添加时间复杂度(作为运行时间测试代码)。
  • 谢谢,让。一开始,我害怕在 StackOverflow 中发布我的代码(负 cmets),但您真的鼓励我继续前进(发布和优化)。祝你好运
【解决方案3】:
def max_gap(N):
    xs = bin(N)[2:].strip('0').split('1')
    return max([len(x) for x in xs])

解释:

  1. 前导零和尾随零对于二进制间隙查找都是多余的 因为它们不受两个 1 的限制(分别为左和右)
  2. 因此,第 1 步左右分条零
  3. 然后除以 1 得到所有 0'z 的序列
  4. 解决方法:0的子串最大长度

【讨论】:

  • 欢迎来到 Stack Overflow!感谢您提供代码 sn-p,它可能会提供一些有限的即时帮助。通过描述为什么这是解决问题的好方法,正确的解释将极大地改进其long-term value,并使其对有其他类似问题的未来读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设。
【解决方案4】:

正如 cmets 中所建议的,itertools.groupby 可以有效地将可迭代的元素(如字符串)进行分组。你可以这样处理:

from itertools import groupby

def count_gap(x):
    b = "{0:b}".format(x)
    return max(len(list(v)) for k, v in groupby(b.strip("0")) if k == "0")

number = 123456
print(count_gap(number))

首先,我们从两端去除所有零,因为间隙必须在两端都有一个。然后itertools.groupby 将 1 和 0 组合在一起,我们将密钥(即“0”或“1”)与一个组一起提取(即,如果我们将其转换为列表,它看起来像“0000”或“11”)。接下来,如果 k 为零,我们收集每个组 v 的长度。并由此确定最大的数字,即零与零之间的最长间隙。

【讨论】:

    【解决方案5】:

    我认为当输入数字为 32 (100000) 时,接受的答案不起作用。这是我的解决方案:

    def solution(N):
        res = 0
        st = -1
        for i in range(N.bit_length()):
            if N & (1 << i):
                if st != -1:
                    res = max(res, i - st - 1)
                st = i
    
        return res
    

    【讨论】:

    • 这是stackoverflow中评论答案的一部分。尽管代码是解释性的,但添加一些解释。
    • 添加说明。
    【解决方案6】:
    def solution(N):
        # write your code in Python 3.6
        count = 0
        gap_list=[]
        bin_var = format(N,"b")
        for bit in bin_var:
            if (bit =="1"):
                gap_list.append(count)
                count =0
            else:
                count +=1
        return max(gap_list)
    

    【讨论】:

      【解决方案7】:

      这是我的解决方案:

      def solution(N):
          num = binary = format(N, "06b")
          char = str(num)
          find=False
          result, conteur=0, 0
      
          for c in char:
              if c=='1' and not find:
                  find = True
                  
              if find and c=='0':
                  conteur+=1
      
              if c=='1':
                  if result<conteur:
                      result=conteur
                  conteur=0
      
          return result
      

      【讨论】:

        【解决方案8】:

        这也有效:

        def binary_gap(n):
            max_gap = 0
            current_gap = 0
        
            # Skip the tailing zero(s)
            while n > 0 and n % 2 == 0:
                n //= 2
        
            while n > 0:
                remainder = n % 2
                if remainder == 0:
                    # Inside a gap
                    current_gap += 1
                else:
                    # Gap ends
                    if current_gap != 0:
                        max_gap = max(current_gap, max_gap)
                        current_gap = 0
                n //= 2
        
            return max_gap
        

        【讨论】:

          【解决方案9】:

          老问题,但我会使用生成器解决它。

          from itertools import dropwhile
          
          # a generator that returns binary 
          # representation of the input
          def getBinary(N):
              while N:
                  yield N%2
                  N //= 2
          
          def longestGap(N):
              longestGap = 0
              currentGap = 0
          
              # we want to discard the initial 0's in the binary
              # representation of the input
              for i in dropwhile(lambda x: not x, getBinary(N)):
                  if i:
                      # a new gap is found. Compare to the maximum
                      longestGap = max(currentGap, longestGap)
                      currentGap = 0
                  else:
                      # extend the previous gap or start a new one
                      currentGap+=1
          
              return longestGap
          

          【讨论】:

            【解决方案10】:

            可以使用 strip() 和 split() 函数来完成: 步骤:

            1. 转换为二进制(去掉前两个字符)
            2. 将int转换为字符串
            3. 分别删除尾随和开始的 0 和 1
            4. 从字符串中用 1 拆分,找到字符串的子序列
            5. 求最长子串的长度

            第二个strip('1')不是强制性的,但它会减少要检查的案例并提高时间复杂度 最坏情况T

            def solution(N):
                return len(max(bin(N)[2:].strip('0').strip('1').split('1')))
            
            

            【讨论】:

              【解决方案11】:

              使用位移运算符的解决方案 (100%)。基本上复杂度是 O(N)。

              def solution(N):
                  # write your code in Python 3.6
                  meet_one = False
                  count = 0
                  keep = []
                  while N:
                      if meet_one and N & 1 == 0:
                          count+=1
                      
                      if  N & 1:
                          meet_one = True
                          keep.append(count)
                          count = 0
                      N >>=1
              
                  return max(keep)
              

              【讨论】:

                【解决方案12】:
                def solution(N):
                # write your code in Python 3.6
                
                    iterable_N = "{0:b}".format(N)
                    max_gap = 0
                    gap_positions = []
                    for index, item in enumerate(iterable_N):
                        if item == "1":
                            if len(gap_positions) > 0:
                               if (index - gap_positions[-1]) > max_gap:
                                    max_gap = index - gap_positions[-1]
                            gap_positions.append(index)
                    max_gap -= 1 
                    return max_gap if max_gap >= 0 else 0
                

                【讨论】:

                  【解决方案13】:

                  这也有效:

                  def solution(N):
                      bin_num = str(bin(N)[2:])
                      list1 = bin_num.split('1')
                      max_gap =0
                      if bin_num.endswith('0'):
                          len1 = len(list1) - 1
                      else:
                          len1 = len(list1)
                      if len1 != 0:
                          for i in range(len1):
                              if max_gap < len(list1[i]):
                                  max_gap = len(list1[i])
                      return max_gap
                  

                  【讨论】:

                    【解决方案14】:
                    def solution(number):
                    
                        bits = [int(digit) for digit in bin(number)[2:]]
                        occurences = [i for i, bit in enumerate(bits) if(bit==1)]
                        res = [occurences[counter+1]-a-1 for counter, a in enumerate(occurences) if(counter+1 < len(occurences))]
                    
                        if(not res):
                            print("Gap: 0")
                        else:
                            print("Gap: ", max(res))
                    
                    number = 1042
                    solution(number)
                    

                    【讨论】:

                      【解决方案15】:

                      这行得通

                      def solution(number):
                          # convert number to binary then strip trailing zeroes
                          binary = ("{0:b}".format(number)).strip("0")
                          longest_gap = 0
                          current_gap = 0
                          for c in binary:
                              if c is "0":
                                 current_gap = current_gap + 1
                              else:
                                 current_gap = 0
                      
                              if current_gap > longest_gap:
                                 longest_gap = current_gap 
                      
                      
                          return longest_gap
                      

                      【讨论】:

                        【解决方案16】:
                        def max_gap(N):
                            bin = '{0:b}'.format(N)
                            binary_gap = []
                            bin_list = [bin[i:i+1] for i in range(0, len(bin), 1)] 
                        
                            for i in range(len(bin_list)):
                                if (bin_list[i] == '1'):
                                    # print(i)
                                    # print(bin_list[i])
                                    # print(binary_gap)
                                    gap = []
                                    for j in range(len(bin_list[i+1:])):
                                        # print(j)
                                        # print(bin_list[j])
                                        if(bin_list[i+j+1]=='1'):
                                            binary_gap.append(j)
                                            # print(j)
                                            # print(bin_list[j])
                                            # print(binary_gap)
                                            break
                                        elif(bin_list[i+j+1]=='0'):
                                            # print(i+j+1)
                                            # print(bin_list[j])
                                            # print(binary_gap)
                                            continue
                                        else:
                                            # print(i+j+1)
                                            # print(bin_list[i+j])
                                            # print(binary_gap)
                                            break
                                else:
                                    # print(i)
                                    # print(bin_list[i])
                                    # print(binary_gap)
                                    binary_gap.append(0)
                        
                        
                            return max(binary_gap)
                            pass
                        

                        【讨论】:

                        【解决方案17】:
                        def find(s, ch):
                            return [i for i, ltr in enumerate(s) if ltr == ch]
                        
                        def solution(N):
                            get_bin = lambda x: format(x, 'b')
                            binary_num = get_bin(N)
                            print(binary_num)
                            binary_str = str(binary_num)
                            list_1s = find(binary_str,'1')
                            diffmax = 0
                            for i in range(len(list_1s)-1):
                                if len(list_1s)<1:
                                    diffmax = 0
                                    break
                                else:
                                    diff = list_1s[i+1] - list_1s[i] - 1
                                    if diff > diffmax:
                                        diffmax = diff
                            return diffmax
                            pass
                        

                        【讨论】:

                        • 你能解释一下你的代码吗?不这样做就删除代码可能没有那么有用。
                        【解决方案18】:
                        def solution(N: int) -> int:
                            binary = bin(N)[2:]
                            longest_gap = 0
                            gap = 0
                            for char in binary:
                                if char == '0':
                                    gap += 1
                                else:
                                    if gap > longest_gap:
                                        longest_gap = gap
                                    gap = 0
                            return longest_gap
                        

                        【讨论】:

                        • 请解释为什么你的答案比其他人好。这将有助于人们从您的回答中学习。
                        【解决方案19】:

                        这是一个使用迭代器和生成器的解决方案,它们将处理边缘情况,例如数字 32 (100000) 的二进制间隙为 0,0 的二进制间隙为 0。它不会创建列表,而是依赖于迭代并一次一步处理位串的元素,以获得高效的内存解决方案。

                        def solution(N):
                            def counter(n):
                                count = 0
                                preceeding_one = False
                                for x in reversed(bin(n).lstrip('0b')):
                                    x = int(x)
                                    if x == 1:
                                        count = 0
                                        preceeding_one = True
                                        yield count
                                    if preceeding_one and x == 0:
                                        count += 1
                                        yield count
                                yield count
                            return(max(counter(N)))
                        

                        【讨论】:

                          【解决方案20】:

                          这里还有一个似乎很容易理解的。

                          def count_gap(x):
                               binary_str = list(bin(x)[2:].strip('0'))
                               max_gap = 0 
                               n = len(binary_str)
                               pivot_point = 0
                          
                               for i in range(pivot_point, n):
                                   zeros = 0
                                   for j in range(i + 1, n):
                                        if binary_str[j] == '0':
                                             zeros += 1 
                                        else:
                                             pivot_point = j
                                             break
                          
                                   max_gap = max(max_gap, zeros)
                          
                               return max_gap
                          

                          【讨论】:

                            【解决方案21】:

                            这真的很老了,我知道。但这是我的:

                            def solution(N):
                                gap_list = [len(gap) for gap in bin(N)[2:].strip("0").split("1") if gap != ""]
                                
                                return max(gap_list) if gap_list else 0
                            

                            【讨论】:

                              【解决方案22】:

                              这是另一个有效的解决方案。希望它可以帮助你。您只需要在函数中传递任意数字,它将返回最长的二进制间隙。

                              def LongestBinaryGap(num):
                              
                              n = int(num/2)
                              bin_arr = []
                              
                              for i in range(0,n):
                                  if i == 0:
                                      n1 = int(num/2)
                                      bin_arr.append(num%2)
                                  else:
                                      bin_arr.append(n1%2)
                                      n1 = int(n1/2)
                              
                                      if n1 == 0:
                                          break
                              
                              print(bin_arr)
                              result = ""
                              count = 0
                              count_arr = []
                              
                              for i in bin_arr:
                                  if result == "found":
                                      if i == 0:
                                          count += 1
                                      else:
                                          if count > 0:
                                              count_arr.append(count)
                                              count = 0
                                  if i == 1:
                                      result = 'found'
                                  else:
                                      pass
                              
                              if len(count_arr) == 0:
                                  return 0
                              else:
                                  return max(count_arr)
                              
                              print(LongestBinaryGap(1130))  # Here you can pass any number.
                              

                              【讨论】:

                                【解决方案23】:

                                我在 python 3.6 中的代码得分 100 获取二进制数..获取1的位置 得到 1.. 之间的 abs 差异对它进行排序

                                 S = bin(num).replace("0b", "")
                                          res = [int(x) for x in str(S)]
                                          print(res)
                                          if res.count(1) < 2 or res.count(0) < 1:
                                              print("its has no binary gap")
                                          else: 
                                            positionof1 = [i for i,x in enumerate(res) if x==1]
                                            print(positionof1)
                                            differnce = [abs(j-i) for i,j in zip(positionof1, positionof1[1:])]
                                            differnce[:] = [differnce - 1 for differnce in differnce]
                                            differnce.sort()
                                            print(differnce[-1])
                                

                                【讨论】:

                                • 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。
                                【解决方案24】:
                                def solution(N):
                                    return len(max(bin(N).strip('0').split('1')[1:]))
                                

                                【讨论】:

                                • 与此处提供的其他解决方案相比,这有什么好处吗?请edit解释。
                                【解决方案25】:
                                def solution(N):
                                    maksimum = 0 
                                    zeros_list = str(N).split('1')
                                    if zeros_list[-1] != "" :
                                        zeros_list.pop()
                                        
                                    for item in zeros_list :
                                        if  len(item) > maksimum :
                                            maksimum = len(item)
                                    return(maksimum)
                                

                                【讨论】:

                                  【解决方案26】:
                                  def solution(N):
                                      # Convert the number to bin 
                                      br = bin(N).split('b')[1]
                                      sunya=[]
                                      groupvalues=[]
                                      for i in br:
                                          count = i
                                          if int(count) == 1:
                                              groupvalues.append(len(sunya))
                                              sunya=[]
                                          if int(count) == 0:
                                              sunya.append('count') 
                                  
                                      return max(groupvalues)
                                  

                                  【讨论】:

                                    【解决方案27】:
                                    def solution(N):
                                        bin_num = str(bin(N)[2:])
                                        bin_num = bin_num.rstrip('0')
                                        bin_num = bin_num.lstrip('0')
                                        list1 = bin_num.split('1')
                                        max_gap = 0
                                    
                                        for i in range(len(list1)):
                                            if len(list1[i]) > max_gap:
                                                max_gap = len(list1[i])
                                    
                                        return (max_gap)
                                    

                                    【讨论】:

                                    • 这适用于任何“二进制间隙”第 1 课代码
                                    • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
                                    • 您的代码甚至没有运行,因为缺少缩进。请解决这个问题!
                                    • @hellow,我在发帖时遇到了问题。代码工作得很好。
                                    • 那么请阅读stackoverflow.com/editing-helpstackoverflow.com/help/how-to-answer。有很多帮助可以帮助您正确格式化您的答案,所以请不要以此为借口;)(在我参加一些驾驶课程之前,我不开车。那(几乎)是一样的。阅读先上说明,然后发布)
                                    猜你喜欢
                                    • 2022-01-16
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2015-01-21
                                    • 2019-03-14
                                    • 2015-06-08
                                    相关资源
                                    最近更新 更多