📌  相关文章
📜  1 和 0 数量相等的最长平衡二进制子串

📅  最后修改于: 2022-05-13 01:56:09.770000             🧑  作者: Mango

1 和 0 数量相等的最长平衡二进制子串

给定一个大小为N的二进制字符串str[] 。任务是找到最长的平衡子串。如果子串包含相等数量的01 ,则它是平衡的。

例子:

天真的方法:一个简单的解决方案是使用两个嵌套循环来生成每个子字符串。第三个循环用于计算当前子字符串中01的数量。然后打印其中最长的子串。
时间复杂度: O(N^3)
辅助空间: O(1)

高效的解决方案:借助预计算,存储从开始到当前索引的0计数和1计数之间的差值。然后可以使用此差异来确定具有相等0s1s的最长子字符串,作为差异数组中任何重复值之间的最长距离。使用基于 Map 的散列进行预计算。请按照以下步骤解决问题:

  • 初始化地图 m[]。
  • m[0]的值设置为-1。
  • 初始化变量count_0、count_1、res、startend
  • 使用变量i遍历字符串str[]并执行以下任务:
    • 10的计数分别记录为count_1count_0
    • 查看count_1count_0之间的当前差异是否已经存在于地图m[]中。如果是,则执行以下任务:
      • 先前出现和当前索引的子字符串具有相同数量的01
      • 如果当前找到的子字符串的长度大于res则将找到的子字符串设置为到目前为止的答案。
    • 如果它是第一次出现,则将当前差值和当前索引存储在映射中,即m[count_1 – count_0]等于i
  • 如果count_0count_1都为0,则打印-1。
  • 否则,从头到尾打印子字符串

下面是上述方法的实现。

C++
// C++ for finding length
// of longest balanced substring
#include 
using namespace std;
 
// Returns length of the longest substring
// with equal number of zeros and ones.
string stringLen(string str)
{
 
    // Create a map to store differences
    // between counts of 1s and 0s.
    map m;
 
    // Initially difference is 0.
    m[0] = -1;
 
    int count_0 = 0, count_1 = 0;
    int start, end, res = 0;
    for (int i = 0; i < str.size(); i++) {
 
        // Keeping track of counts of
        // 0s and 1s.
        if (str[i] == '0')
            count_0++;
        else
            count_1++;
 
        // If difference between current counts
        // already exists, then substring between
        // previous and current index has same
        // no. of 0s and 1s. Update result if this
        // substring is more than current result.
        if (m.find(count_1 - count_0) != m.end()) {
 
            if ((i - m[count_1 - count_0]) > res) {
 
                start = m.find(
                             count_1 - count_0)
                            ->second;
                end = i;
                res = end - start;
            }
        }
 
        // If current difference
        // is seen first time.
        else
            m[count_1 - count_0] = i;
    }
 
    if (count_0 == 0 || count_1 == 0)
        return "-1";
 
    // Return the substring
    // between found indices
    return str.substr(start + 1, end + 1);
}
 
// Driver Code
int main()
{
    string str = "110101010";
    cout << stringLen(str);
    return 0;
}


Java
// Java code for the above approach
import java.io.*;
class GFG
{
 
  // Returns length of the longest substring
  // with equal number of zeros and ones.
  static String stringLen(String str)
  {
 
    // Create a map to store differences
    // between counts of 1s and 0s.
    int [] m = new int[100000];
 
    // Initially difference is 0.
    m[0] = -1;
 
    int count_0 = 0; int count_1 = 0;
    int start = 0; int end = 0; int res = 0;
    for (int i = 0; i < str.length(); i++) {
 
      // Keeping track of counts of
      // 0s and 1s.
      if (str.charAt(i) == '0')
        count_0++;
      else
        count_1++;
 
      // If difference between current counts
      // already exists, then substring between
      // previous and current index has same
      // no. of 0s and 1s. Update result if this
      // substring is more than current result.
      if (m[count_1 - count_0]!= 0) {
 
        if ((i - m[count_1 - count_0]) > res) {
 
          start = m[count_1 - count_0];
 
          end = i;
          res = end - start;
        }
      }
 
      // If current difference
      // is seen first time.
      else
        m[count_1 - count_0] = i;
    }
 
    if (count_0 == 0 || count_1 == 0)
      return "-1";
 
    // Return the substring
    // between found indices
    return str.substring(start , end + 2);
  }
 
  // Driver Code
  public static void main (String[] args)
  {
    String str = "110101010";
 
    System.out.println(stringLen(str));
  }
}
 
// This code is contributed by Potta Lokesh


Python3
# Python for finding length
# of longest balanced substring
 
# Returns length of the longest substring
# with equal number of zeros and ones.
def stringLen (str) :
 
    # Create a map to store differences
    # between counts of 1s and 0s.
    m = {}
 
    # Initially difference is 0.
    m[0] = -1
 
    count_0 = 0
    count_1 = 0
    res = 0
    for i in range(len(str)):
 
        # Keeping track of counts of
        # 0s and 1s.
        if (str[i] == '0'):
            count_0 += 1
        else:
            count_1 += 1
 
        # If difference between current counts
        # already exists, then substring between
        # previous and current index has same
        # no. of 0s and 1s. Update result if this
        # substring is more than current result.
        if ((count_1 - count_0) in m):
 
            if ((i - m[count_1 - count_0]) > res):
 
                start = m[(count_1 - count_0)]
                end = i
                res = end - start
             
        # If current difference
        # is seen first time.
        else:
            m[count_1 - count_0] = i
     
    if (count_0 == 0 or count_1 == 0):
        return "-1"
 
    # Return the substring
    # between found indices
    return str[start + 1 : start + 1 + end + 1]
 
# Driver Code
str = "110101010"
print(stringLen(str))
 
# This code is contributed by Saurabh Jaiswal


C#
// C# code for the above approach
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG
{
 
  // Returns length of the longest substring
  // with equal number of zeros and ones.
  static string stringLen(string str)
  {
 
    // Create a map to store differences
    // between counts of 1s and 0s.
    int []m = new int[100000];
 
    // Initially difference is 0.
    m[0] = -1;
 
    int count_0 = 0; int count_1 = 0;
    int start = 0; int end = 0; int res = 0;
    for (int i = 0; i < str.Length; i++) {
 
      // Keeping track of counts of
      // 0s and 1s.
      if (str[i] == '0')
        count_0++;
      else
        count_1++;
 
      // If difference between current counts
      // already exists, then substring between
      // previous and current index has same
      // no. of 0s and 1s. Update result if this
      // substring is more than current result.
      if (m[count_1 - count_0]!= 0) {
 
        if ((i - m[count_1 - count_0]) > res) {
 
          start = m[count_1 - count_0];
 
          end = i;
          res = end - start;
        }
      }
 
      // If current difference
      // is seen first time.
      else
        m[count_1 - count_0] = i;
    }
 
    if (count_0 == 0 || count_1 == 0)
      return "-1";
 
    // Return the substring
    // between found indices
    return str.Substring(start, end - start + 2);
  }
 
  // Driver Code
  public static void Main ()
  {
    string str = "110101010";
 
    Console.Write(stringLen(str));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript


输出
10101010

时间复杂度: O(N)
辅助空间: O(N)