最近一次采访中,我被要求编写一个程序来查找最大的子字符串,该子字符串在二进制字符串中包含相等数量的0
和1
。
例如:
如果给定的字符串为1010111
,则输出将为1010
,因为它包含2个0
和2个1
s。
我做了很多尝试,但无论如何都无法为该问题构建算法。
有人可以给我一个开始的方法,以解决这个问题或使用什么数据结构吗?
答案 0 :(得分:8)
以下内容将在 O(n)时空中工作, n 是字符串中的字符数。
balance
和1
时间中看到的0
和string
当前first
(或失衡)的情况字符串具有相同的余额(一个数组或映射最多包含n
个条目)string
,然后为每个字符...
balance
,将"1"
计为1
,将"0"
计为-1
,反之亦然balance
best
,请记住新的最长子字符串first
职位Python中的示例代码:
string = "1010111000"
first = {0: 0} # map or array; 0th element is 0
balance = 0 # initially, 1 and 0 are balanced
best = "" # best substring found
for i, c in enumerate(string): # (i, c) = (index, character)
balance += 1 if c == "1" else -1 # update balance
if balance not in first: # first time we see this balance?
first[balance] = i+1 # add next(!) position to map/array
elif i - first[balance] > len(best): # otherwise, if new longest substring
best = string[first[balance]:i+1] # update best with slice of string
print(i, c, balance, best, first) # debugging/demo output
输出:
0 1 1 {0: 0, 1: 1}
1 0 0 10 {0: 0, 1: 1}
2 1 1 10 {0: 0, 1: 1}
3 0 0 1010 {0: 0, 1: 1}
4 1 1 1010 {0: 0, 1: 1}
5 1 2 1010 {0: 0, 1: 1, 2: 6}
6 1 3 1010 {0: 0, 1: 1, 2: 6, 3: 7}
7 0 2 1010 {0: 0, 1: 1, 2: 6, 3: 7}
8 0 1 01011100 {0: 0, 1: 1, 2: 6, 3: 7}
9 0 0 1010111000 {0: 0, 1: 1, 2: 6, 3: 7}
答案 1 :(得分:4)
我会这样处理
初始化可变整数和且maxlength = minimum
定义一个以sum为键且索引为值的hashmap
对于给定字符串中的每个值
sum + = arr [i] == 0?然后加-1,否则加1
如果总和为0,则maxlength = maxlength或index + 1,因为这是一个可能的答案
否则,如果字典包含该和值,maxlength = maxlength或 (i -index hash [sum])较早发现的和值有助于结果。
如果sum的值不在哈希图中,则更新哈希图 索引
返回最大长度。
这是我上面提到的示例,在代码working example中,您可以尝试更改测试用例,以了解其对各种测试用例的工作方式,还尝试打印哈希图并通过以下方式进行跟踪来加深了解。
答案 2 :(得分:2)
就最佳化而言,这种解决方案不是最佳解决方案,但是在匆忙和面试的压力下,可以快速地思考,绘制和解释这种解决方案。
我要嵌套2个循环。
1从0到len-2(递增)(最小长度应为2)
1从len到上一个循环值+ 2(递减)(最小长度应为2)
获取循环的相应迭代器的子字符串
计算字符是否相等。
然后,如果为true,则与存储的结果长度进行比较,如果长度较大,则覆盖结果。
以0100
为例,将对这些值进行测试:
// result = ''
0100 //not balanced
010 //not balanced
01 //balanced AND length is greated than result's one. result = '01'
100 //not balanced
10 //balanced BUT length is not greated than result's one
00 //not balanced
JavaScript示例(我对其进行了一些调整以优化迭代次数,但方法相同):
var iterations = 0;
function IsBalanced(input, char1, char2)
{
if (input.length % 2 != 0) // odd length can't be balanced
{
++iterations;
return (false);
}
let char1count = 0;
let char2count = 0;
let len = input.length;
for (let i = 0; i < len; ++i)
{
++iterations;
if (input[i] == char1)
++char1count;
else
++char2count;
}
return (char1count == char2count);
}
function findLargest(input, char1, char2)
{
let len = input.length;
let result = '';
for (let k = 0; k < len - 1; ++k)
{
// This is a tweak to reduce the number of iterations
// To avoid testing a substring smaller than the current result
// |
// |
// v----------------------v
for (let l = len; l - k > result.length && l > k + 1; --l)
{
tempResult = input.substring(k, l);
if (IsBalanced(tempResult, char1, char2) && tempResult.length > result.length)
result = tempResult;
}
}
return (result);
}
console.log("Input : 1010111 - result : " + findLargest("1010111", "1", "0") + " original size : " + "1010111".length + " - iterations : " + iterations);
iterations = 0;
console.log("Input : ababaaa - result : " + findLargest("ababaaa", "a", "b") + " original size : " + "ababaaa".length + " - iterations : " + iterations);
iterations = 0;
console.log("Input : 00100100 - result : " + findLargest("00100100", "1", "0") + " original size : " + "00100100".length + " - iterations : " + iterations);
iterations = 0;
console.log("Input : 1111100000 - result : " + findLargest("1111100000", "1", "0") + " original size : " + "1111100000".length + " - iterations : " + iterations);
iterations = 0;
console.log("Input : 0001111111111010001111100000000001111111111 - result : " + findLargest("0001111111111010001111100000000001111111111", "1", "0") + " original size : " + "0001111111111010001111100000000001111111111".length + " - iterations : " + iterations);
iterations = 0;
console.log("Input : 0000000000000000000000000000000000000000000000000001 - result : " + findLargest("0000000000000000000000000000000000000000000000000001", "1", "0") + " original size : " + "0000000000000000000000000000000000000000000000000001".length + " - iterations : " + iterations);
答案 3 :(得分:0)
一种非常简单的方法:
简单和O(n ^ 2)的时间和空间复杂度。
编辑:迭代过程[项目符号4]不会改变最坏情况下的复杂度,但是我上面描述的方式可以创建更好的平均情况下的速度。数组可以可视化为三角矩阵,并且可以像这样(C ++样式)进行迭代:
// comment: n = number of 1's and 0's in the string;
int start = 0, end = 0;
for ( int distance = n - 1; distance > 0; distance = distance - 1 )
{
int row = 0, column = distance;
while ( column < n )
{
if ( array [ row ] [ column ] == 0 )
{
start = row;
end = column;
// comment: Largest substring of equal-ones-and-zeros found
return std :: make_pair ( start, end );
}
row = row + 1;
column = column + 1;
}
}