我正在寻找一种有效的算法来查找二进制字符串中最长的零运行。我的实现是在Python 2.7中,但我需要的只是算法的概念。
例如,给定'0010011010000',函数应返回4.
答案 0 :(得分:8)
我认为没有什么比在单个字符串上传递更好,计算当前序列长度(并更新最大值)。
如果用"二进制字符串"你的意思是原始位,你可以一次读取一个字节并在那里提取8位(使用位移或屏蔽)。这并不会改变整体算法或其复杂性。
答案 1 :(得分:2)
应该可以击败明显的算法。这个想法是,如果你已经有一个长度为0的0并且你看到两个1不超过N个位置,你不需要检查它们之间的任何位置。因此,从末尾而不是从头开始检查候选零序列。在最糟糕的情况下,你只需检查所有元素,就像在天真的方法中一样,但平均来说它会小于那个。
所以算法就像这样(伪代码,未经测试)
maxrun = 0
curpos = 0
runstart = 0
runend = 0
while curpos + maxrun < array.length
broken = false
for i = curpos + maxrun, i >= curpos and not broken, --i
if array[i] == 1
broken = true
curpos = i + 1
if not broken
runstart = curpos
# found a longer run of 0s
# now extend it to the end
maxrun++
curpos += maxrun
while curpos < array.length and array[curpos] == 0
maxrun++
# ok found the 1 at the right end of the run
# go to the next position and start over
runend = curpos
curpos++
# the longest run of 0s is [runstart, runend)
答案 2 :(得分:1)
为了找到二进制字符串中连续的最大零,我建议如下:
int maxConsecutiveZeros(String binaryString) {
int maxcount = Integer.MIN_VALUE;
int currcount = 0;
for(int i=0; i < binaryString.length(); i++) {
if(binaryString.charAt(i) == '0') {
currcount++;
} else {
maxcount = Math.max(currcount, maxcount);
currcount = 0;
}
}
return maxcount;
}
您应该单独处理binaryString以零结尾的情况。将该部分添加到提供的大纲中,您就完成了。
这种方法的复杂性在二进制字符串的长度上是线性的。
答案 3 :(得分:1)
这取决于你的效率是什么意思。
如果您的目的是最大限度地减少运行时间,那么您基本上必须逐个字符地检查字符串,分析连续零的运行并跟踪最长的,如:
def longRunZeros(s):
big = 0
curr = 0
for c in s:
if c == '0':
curr += 1
else:
if curr > big:
big = curr
curr = 0
if curr > big:
big = curr
return big
print longRunZeros('0010011010000')
如果您正在谈论程序员效率,请执行以下操作:
def longRunZeros(s):
return max(len(i) for i in s.split('1'))
代替。
它不一定能以最快的速度运行,但它可以让你有更多的时间,也许可以用来分析你是否需要这个操作的原始速度。它几乎可以肯定不那么容易出错。
至于你是否需要速度,请考虑一下。对于25M字符串,逐字符方法需要2.826秒的CPU时间进行一百万次迭代。对于相同的工作负载 1 ,split
方法需要3.186秒。
所以,除非你的字符串长度超过25M或者你需要做的时间超过一百万次,否则它不会产生太大的影响,我倾向于选择对于我作为开发人员来说更容易的方法。
附录:在支持这里无关的差异表现之后,我觉得有点虚伪地提到John La Rooy在评论中显示的另一种方法实际上似乎比我的两种方法都要快一些。
但是,为了完整起见,我还会用吊索和箭头指出那一个:
def longRunZeros(s):
return len(max(s.split('1')))
这似乎是大约1.092
的平均值,这是上述逐个字符情况的两倍。
1 在我的环境中,这些数字是五次运行的平均值,我不保证他们会在其他任何地方举行。
如果您曾参与优化工作,您应该知道它应该在您的实际环境中进行衡量,而不是依赖于某些随机的说法 - 但是非常好看的人在互联网上: - )
答案 4 :(得分:1)
编译的正则表达式可能会快得多,但我还没有真正测试过它。尽管如此:
>>> binstr = '0010011010000'
>>> import re
>>> zeros = re.compile(r'0+')
>>> max(len(m) for m in zeros.findall(binstr))
4
答案 5 :(得分:0)
好的,正如有人提到的,它的类型是 String ,那么我认为你无法逃避O(| N |)这是I / O时间。我在这里只想说它是一个整数,然后你可以做得更快,例如:
#include<bits/stdc++.h>
using namespace std;
int n;
void binary(int x){
if(x){
binary(x>>1);
if(x&1) putchar('1');
else putchar('0');
}
}
int main() {
scanf("%d", &n);
while(n){
binary(n);
puts("");
int x = log2(n&-n);
printf("Zero range: %d\n", x);
n >>= (x+1);
}
return 0;
}
忽略打印部分,我认为是O(lg N)? (警告:因为这是处理整数,不考虑填充零,但它应该不难)
答案 6 :(得分:0)
这有点乱,我知道如果我多想一点,我可以改善结局
def solution(N):
y = [int(x) for x in bin(N)[2:]]
lst,zero = [],0
for r in y:
if r == 0:
zero +=1
else:
if zero > 0:
lst.append(zero)
zero = 0
try:
return max(lst)
except Exception as E:
return 0
你们许多人不需要最后一部分而只返回max(lst)