【问题标题】:Find the largest substring which contains equal number of 0s and 1s in a binary string在二进制字符串中找到包含相同数量的 0 和 1 的最大子字符串
【发布时间】:2019-02-04 11:53:08
【问题描述】:

最近在一次采访中,我被要求编写一个程序来查找在二进制字符串中包含相等数量的0s 和1s 的最大子字符串。

例如:

如果给定的字符串是1010111,那么输出将是1010,因为它包含2个0s和2个1s。

我尝试了很多,但无论如何都想不出为这个东西构建算法。

有人可以让我先了解如何继续或使用什么数据结构来解决这个问题吗?

【问题讨论】:

  • 如果您将 0 值视为 -1 会有帮助吗?将问题简化为找到总和为 0 的数组的最大长度?
  • 不会0101(从第一个 0 开始)也可以吗?还是它是第一个被发现的?
  • @SamerTufail 我认为考虑到任何2个数字甚至字符都可以替换这个问题,所以我认为找到0的总和是不正确的
  • @M.K 因为重点是找最长的,所以我觉得0101也可以考虑
  • 搜索互联网会帮助您找到一些算法和实现。例如,我在这里找到了一个:geeksforgeeks.org/…

标签: algorithm language-agnostic


【解决方案1】:

以下将在O(n)时间和空间中工作,n是字符串中的字符数。

  • 跟踪您在string 中看到的10 的当前balance(或不平衡),以及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}

【讨论】:

  • 不平衡是指在数组/字典中保持 0 和 1 的计数吗?或计数之间的差异
  • balance += 1 if c == "1" else -1 和我在第一条评论中所说的差不多,现在问题已经减少到使用sum = 0 找到最大子数组
  • @SamerTufail 是的,我想我们在这里有同样的想法。从您的评论中并不完全清楚,特别是您不能只考虑 sum=0 的所有位置,而是所有与以前的值相同的位置。
  • you can't just regard all the positions where sum=0 - 为什么不呢?如果是0,那么这意味着sum 的值是sum-1,其中总和从0 开始,所有带有sum = 0 的位置都是潜在的答案。
  • @SamerTufail 也许这不是很清楚。我的意思是你不能只考虑(在我的代码中)“余额”为零的地方,因为那些地方只是从第一个索引开始的子字符串。您还需要其他余额或总和的第一位置的列表/地图,就像您的算法中一样。
【解决方案2】:

我会这样处理它

  • 初始化一个变量整数 sum 和 maxlength = minimum

  • 定义一个 hashmap,其中 sum 为 key,index 为 value

  • 对于给定字符串中的每个值

    • 总和 += arr[i] == 0 ?然后添加 -1 否则添加 1

    • 如果总和为 0 maxlength = maxlength 或 index + 1,因为这是一个潜在的答案

    • 否则,如果字典包含该总和值,maxlength = maxlength 或 (i -index hash[sum]) 之前发现的对结果有贡献的总和值。

    • 如果 sum 的值不在哈希图中,则更新哈希图 索引

    • 返回最大长度。

这是我上面提到的一个例子,在代码中:working example 你可以尝试更改测试用例,看看它如何适用于各种测试用例,尝试打印哈希图并手动跟踪它加深理解。

【讨论】:

    【解决方案3】:

    这个解决方案在优化方面并不是最好的,但是在匆忙和面试的压力下,这个解决方案可以快速思考、绘制和解释。

    我会嵌套 2 个循环。

    1 从 0 开始到 len - 2(递增)(最小长度应该是 2)

    1 从 len 开始到上一个循环值 + 2(递减)(最小长度应为 2)

    获取循环对应迭代器的子串

    如果字符相等则计数。

    然后,如果为真,则与存储的结果长度进行比较,如果长度更大,则覆盖结果。

    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);

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 1970-01-01
      • 2021-09-20
      • 2013-03-24
      • 2018-10-15
      • 2016-10-01
      • 2021-12-01
      • 2022-11-22
      • 1970-01-01
      相关资源
      最近更新 更多