Python:在整数的二进制表示中查找最长的二进制间隙
Posted
技术标签:
【中文标题】Python:在整数的二进制表示中查找最长的二进制间隙【英文标题】:Python: Find longest binary gap in binary representation of an integer number 【发布时间】: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。
【参考方案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,您的代码比我提供的要慢得多。我将在答案中添加时间复杂度(作为运行时间测试代码)。
谢谢,让。一开始,我害怕在 *** 中发布我的代码(负 cmets),但您真的鼓励我继续前进(发布和优化)。祝你好运【参考方案3】:
def max_gap(N):
xs = bin(N)[2:].strip('0').split('1')
return max([len(x) for x in xs])
解释:
-
前导零和尾随零对于二进制间隙查找都是多余的
因为它们不受两个 1 的限制(分别为左和右)
因此,第 1 步左右分条零
然后除以 1 得到所有 0'z 的序列
解决方法: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
【讨论】:
这是***中评论答案的一部分。尽管代码是解释性的,但添加一些解释。 添加说明。【参考方案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() 函数来完成: 步骤:
-
转换为二进制(去掉前两个字符)
将int转换为字符串
分别删除尾随和开始的 0 和 1
从字符串中用 1 拆分,找到字符串的子序列
求最长子串的长度
第二个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
【讨论】:
你应该edit你的答案添加一个minimal reproducible example来证明问题。【参考方案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,我在发帖时遇到了问题。代码工作得很好。 那么请阅读***.com/editing-help和***.com/help/how-to-answer。有很多帮助可以帮助您正确格式化您的答案,所以请不要以此为借口;)(在我参加一些驾驶课程之前,我不开车。那(几乎)是一样的。阅读先上说明,然后发布)以上是关于Python:在整数的二进制表示中查找最长的二进制间隙的主要内容,如果未能解决你的问题,请参考以下文章