尽量减少从前端或末端的移除,使二进制字符串处于平衡状态的实例

114 阅读3分钟

尽量减少从前端或末端的移除,使二进制字符串处于平衡状态

给定一个大小为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个索引。

下面是上述方法的实现。

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)