尽量减少从前端或末端的移除,使二进制字符串处于平衡状态
给定一个大小为N 的二进制字符串S , 任务是找出从二进制字符串的开始或结束位置所需的最小去除次数,以使去除后的最终字符串中的**'0'和'1'** 的数量相等。
例子。
输入。S = "0111010"
**输出。**3
**解释。**从给定的字符串的前面删除3个元素。
删除后的字符串是 "1010",其中0和1的数量相等。输入。S = "01100101"
**输出。**0
一个使用前缀和技术的方法。
解决这个问题的思路是基于这样的观察
对于任何有效的子串,如果0的数量和1的数量相等,那么子串的值之和也将是0,如果我们认为字符 "1 "的值是1, "0 "的值是**-1**。
因此,问题的关键在于找到最长的子串,而我们假设子串的值之和为0,找到最长的有效子串后,剩下的部分将被删除。
按照下面的步骤来实现上述想法。
- 遍历给定二进制字符串的长度。
- 创建一个变量(例如prefixSum) ,用于计算从开始 到第i个位置的前缀和,并创建一个变量result ,用于存储最长的有效子串的长度。
- 创建一个map(例如unmap) ,用于存储从第i个索引结束的前缀Sum。
- 通过考虑字符'1'到1和'0'到-1的值来计算prefixSum 。
- 检查prefixSum的值。
- 如果prefixSum 的值等于0, 那么就用其当前的子串长度来更新结果。
- 否则,检查这个prefixSum 之前是否已经发生过。
- 如果prefixSum 已经发生过,那么。
- 有效子串的长度将是**(i - unmap[prefixSum])(也就是说,如果我们从当前的prefixSum** 中删除这个已经发生的prefixSum 值,那么剩余子串的值将导致0)。
- 否则,将这个当前的prefixSum 已经发生在地图中的第i个索引。
- 如果prefixSum 已经发生过,那么。
下面是上述方法的实现。
C++
// C++ code to implement the approach.
#include <bits/stdc++.h>
using namespace std;
// Function to solve the problem
int minRemoval(string& s)
{
// Storing prefixSum with index
// of its first occurrence
unordered_map<int, int> unmap;
int n = s.size();
// For storing the prefix Sum
// ending at ith index
int prefixSum = 0;
// For keeping the length of
// longest binary string where
// number of zero and ones are equal
int result = 0;
// Iterate over the string
for (int i = 0; i < n; i++) {
prefixSum += ((s[i] == '1') ? 1 : -1);
if (prefixSum == 0) {
result = max(result, i + 1);
}
// Check if prefixSum have
// previously occurred or not
if (unmap.count(prefixSum)) {
// Update the result with
// this valid substring
result = max(result,
i - unmap[prefixSum]);
}
else {
// Store this prefixSum has
// occur at ith index
// in the map.
unmap[prefixSum] = i;
}
}
// Return the remaining length
// other than the longest
// valid substring.
return n - result;
}
// Driver code
int main()
{
string S = "0111010";
// Function call
int result = minRemoval(S);
cout << result << endl;
return 0;
}
Java
/*package whatever //do not write package name here */
import java.io.*;
import java.util.*;
class GFG {
// Function to solve the problem
static int minRemoval(String s)
{
// Storing prefixSum with index
// of its first occurrence
HashMap<Integer,Integer> mp = new HashMap<>();
int n = s.length();
// For storing the prefix Sum
// ending at ith index
int prefixSum = 0;
// For keeping the length of
// longest binary string where
// number of zero and ones are equal
int result = 0;
// Iterate over the string
for (int i = 0; i < n; i++) {
prefixSum += ((s.charAt(i) == '1') ? 1 : -1);
if (prefixSum == 0) {
result = Math.max(result, i + 1);
}
// Check if prefixSum have
// previously occurred or not
if (mp.containsKey(prefixSum)) {
// Update the result with
// this valid substring
result = Math.max(result,i - mp.get(prefixSum));
}
else {
// Store this prefixSum has
// occur at ith index
// in the map.
mp.put(prefixSum,i);
}
}
// Return the remaining length
// other than the longest
// valid substring.
return n - result;
}
public static void main (String[] args) {
String S = "0111010";
// Function call
int result = minRemoval(S);
System.out.println(result);
}
}
// This code is contributed by aadityaburujwale.
Python
# Python code for the above approach
# Function to solve the problem
def minRemoval(s):
# Storing prefixSum with index of
# its first occurrence.
mp = {}
n = len(s)
# For storing the prefix Sum ending
# at ith index
prefixSum = 0
# For keeping the length of longest
# binary string where number of zero
# and ones are equal.
result = 0
# Iterate over the string
for i in range(n):
prefixSum += 1 if(s[i] == '1') else -1
if prefixSum is 0:
result = max(result, i+1)
# Check if prefixSum have previously
# occurred or not
if prefixSum in mp:
# Update the result with this
# valid substring
result = max(result, i-mp[prefixSum])
else:
# Store this prefixSum has occur at
# ith index in the map.
mp[prefixSum] = i
# Return the remaining length other
# than the longest valid substring.
return n-result
S = "0111010"
# Function call
result = minRemoval(S)
print(result)
# This code is contributed by lokesh.
Javascript
<script>
// JavaScript code to implement the approach.
// Function to solve the problem
const minRemoval = (s) => {
// Storing prefixSum with index
// of its first occurrence
let unmap = {};
let n = s.length;
// For storing the prefix Sum
// ending at ith index
let prefixSum = 0;
// For keeping the length of
// longest binary string where
// number of zero and ones are equal
let result = 0;
// Iterate over the string
for (let i = 0; i < n; i++) {
prefixSum += ((s[i] == '1') ? 1 : -1);
if (prefixSum == 0) {
result = Math.max(result, i + 1);
}
// Check if prefixSum have
// previously occurred or not
if (prefixSum in unmap) {
// Update the result with
// this valid substring
result = Math.max(result,
i - unmap[prefixSum]);
}
else {
// Store this prefixSum has
// occur at ith index
// in the map.
unmap[prefixSum] = i;
}
}
// Return the remaining length
// other than the longest
// valid substring.
return n - result;
}
// Driver code
let S = "0111010";
// Function call
let result = minRemoval(S);
document.write(result);
// This code is contributed by rakeshsahni
</script>
输出
3
时间复杂度。O(N),其中N是给定二进制字符串的长度。
辅助空间。O(N)