最小化交替子序列的计数以将给定的二进制字符串与子序列号相除
给定一个长度为N的二进制字符串S。任务是找到以下内容:
- 子序列的最小数目,字符串S可以被划分,使得子序列不包含相邻的零或一。
- 字符串S的每个字符所属的子序列号。
如果有很多答案,则输出任何答案。
例子:
Input: S = “0011”, N = 4
Output:
2
1 2 2 1
Explanation:
There can be a minimum of 2 subsequences such that they donot have any adjacent zeroes or ones.
Subsequence 1: “01”
Subsequence 2: “01”
Also, the first character of S(‘0’) belongs to subsequence 1(“01”)
Second character of S(‘0’) belongs to subsequence 2(“01”)
Third character of S(‘1’) belongs to subsequence 2(“01”)
Fourth character of S(‘1’) belongs to subsequence 1(“01”)
Input: S = “1000110”, N = 7
Output:
3
1 1 2 3 3 2 2
方法:需要注意的是,子序列是可以通过删除零个或多个元素而不改变剩余元素的顺序从给定序列导出的序列。现在,请按照以下步骤解决问题:
- 创建一个向量ans来存储字符串S的每个字符所属的子序列。
- 另外,创建两个向量endZero和endOne分别存储以“0”和“1”结尾的子序列。
- 因为子序列中不能有相邻的零或一。因此,如果一个字符是'0' ,则要放入子序列中的下一个字符必须是'1' ,反之亦然。
- 现在,使用循环遍历S的每个字符并检查它是'0'还是'1' 。此外,声明一个变量newSeq ,它表示如果遇到连续的零或一,则要形成的新子序列。
- 如果一个字符是'0' ,检查向量endOne是否为空:
- 如果为空,则将newSeq推入endZero 。
- 否则,将endOne的最后一个子序列放入newSeq中。现在, endOne的最后一个子序列不再以'1'结尾,因为它已附加了'0' 。因此,将其推入endZero 。
- 同样,如果S中的字符为'1' ,则执行与上述相同的步骤,即检查向量endZero是否为空:
- 如果为空,则将newSeq推入endOne 。
- 否则,将endZero的最后一个子序列放入newSeq中。现在, endZero的最后一个子序列不再以“0”结尾,因为“1”已附加到它上面。因此,将其推入endOne 。
- 然后,将newSeq推入向量ans中。
- 对S的每个字符重复上述步骤。
- 子序列的最小数量将由endZero和endOne的大小之和给出。
- 最后,输出最小子序列数和向量ans 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the minimum number of
// subsequences into which S has to divide
// and the subsequences to which each character
// of S belongs to.
void findSeq(string S, int N)
{
// Stores the subsequences to which each
// character of S belongs to.
vector ans(N);
// Store the subsequences ending with zeroes
// and ones respectively.
vector endZero, endOne;
// Loop to traverse each character of S
for (int i = 0; i < N; ++i) {
// Stores the number of new
// subsequence to be formed
int newSeq = endZero.size()
+ endOne.size();
// If the character is '0'
if (S[i] == '0') {
// If there is no string
// which ends with '1'
if (endOne.empty()) {
// Push newSeq into endZero
endZero.push_back(newSeq);
}
else {
// Put the last element
// of endOne into newSeq
newSeq = endOne.back();
// Remove the last
// element of endOne
endOne.pop_back();
// newSeq ends with '0'
endZero.push_back(newSeq);
}
}
else {
// If there is no string
// which ends with '0'
if (endZero.empty()) {
// Push newSeq into endOne
endOne.push_back(newSeq);
}
else {
// Put the last element
// of endZero into newSeq
newSeq = endZero.back();
// Remove the last element of endOne
endZero.pop_back();
// newSeq ends with '1'
endOne.push_back(newSeq);
}
}
// Put newSeq into vector ans
ans[i] = newSeq;
}
// Output the minimum
// number of subsequences
cout << endZero.size()
+ endOne.size()
<< endl;
// Output the subsequences
// to which each character
// of S belongs to
for (int i = 0; i < N; ++i) {
// Add 1 as the index starts from 0
cout << ans[i] + 1 << " ";
}
}
// Driver Code
int main()
{
// Given input
string S = "1000110";
int N = 7;
// Function Call
findSeq(S, N);
return 0;
}
Java
// Java program for the above approach
import java.util.ArrayList;
class GFG {
// Function to find the minimum number of
// subsequences into which S has to divide
// and the subsequences to which each character
// of S belongs to.
public static void findSeq(String S, int N)
{
// Stores the subsequences to which each
// character of S belongs to.
int[] ans = new int[N];
// Store the subsequences ending with zeroes
// and ones respectively.
ArrayList endZero = new ArrayList();
ArrayList endOne = new ArrayList();
// Loop to traverse each character of S
for (int i = 0; i < N; ++i) {
// Stores the number of new
// subsequence to be formed
int newSeq = endZero.size() + endOne.size();
// If the character is '0'
if (S.charAt(i) == '0') {
// If there is no string
// which ends with '1'
if (endOne.isEmpty()) {
// Push newSeq into endZero
endZero.add(newSeq);
} else {
// Put the last element
// of endOne into newSeq
newSeq = endOne.get(endOne.size() - 1);
// Remove the last
// element of endOne
endOne.remove(endOne.size() - 1);
// newSeq ends with '0'
endZero.add(newSeq);
}
} else {
// If there is no string
// which ends with '0'
if (endZero.isEmpty()) {
// Push newSeq into endOne
endOne.add(newSeq);
} else {
// Put the last element
// of endZero into newSeq
newSeq = endZero.get(endZero.size() - 1);
// Remove the last element of endOne
endZero.remove(endZero.size() - 1);
// newSeq ends with '1'
endOne.add(newSeq);
}
}
// Put newSeq into vector ans
ans[i] = newSeq;
}
// Output the minimum
// number of subsequences
System.out.println(endZero.size() + endOne.size());
// Output the subsequences
// to which each character
// of S belongs to
for (int i = 0; i < N; ++i) {
// Add 1 as the index starts from 0
System.out.print(ans[i] + 1 + " ");
}
}
// Driver Code
public static void main(String args[]) {
// Given input
String S = "1000110";
int N = 7;
// Function Call
findSeq(S, N);
}
}
// This code is contributed by gfgking.
Python3
# python program for the above approach
# Function to find the minimum number of
# subsequences into which S has to divide
# and the subsequences to which each character
# of S belongs to.
def findSeq(S, N):
# Stores the subsequences to which each
# character of S belongs to.
ans = [0 for _ in range(N)]
# Store the subsequences ending with zeroes
# and ones respectively.
endZero = []
endOne = []
# Loop to traverse each character of S
for i in range(0, N):
# Stores the number of new
# subsequence to be formed
newSeq = len(endZero) + len(endOne)
# If the character is '0'
if (S[i] == '0'):
# If there is no string
# which ends with '1'
if (len(endOne) == 0):
# Push newSeq into endZero
endZero.append(newSeq)
else:
# Put the last element
# of endOne into newSeq
newSeq = endOne[len(endOne) - 1]
# Remove the last
# element of endOne
endOne.pop()
# newSeq ends with '0'
endZero.append(newSeq)
else:
# If there is no string
# which ends with '0'
if (len(endZero) == 0):
# Push newSeq into endOne
endOne.append(newSeq)
else:
# Put the last element
# of endZero into newSeq
newSeq = endZero[len(endZero) - 1]
# Remove the last element of endOne
endZero.pop()
# newSeq ends with '1'
endOne.append(newSeq)
# Put newSeq into vector ans
ans[i] = newSeq
# Output the minimum
# number of subsequences
print(len(endZero) + len(endOne))
# Output the subsequences
# to which each character
# of S belongs to
for i in range(0, N):
# Add 1 as the index starts from 0
print(ans[i] + 1, end=" ")
# Driver Code
if __name__ == "__main__":
# Given input
S = "1000110"
N = 7
# Function Call
findSeq(S, N)
# This code is contributed by rakeshsahni
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to find the minimum number of
// subsequences into which S has to divide
// and the subsequences to which each character
// of S belongs to.
public static void findSeq(String S, int N)
{
// Stores the subsequences to which each
// character of S belongs to.
int[] ans = new int[N];
// Store the subsequences ending with zeroes
// and ones respectively.
List endZero = new List();
List endOne = new List();
// Loop to traverse each character of S
for (int i = 0; i < N; ++i)
{
// Stores the number of new
// subsequence to be formed
int newSeq = endZero.Count + endOne.Count;
// If the character is '0'
if (S[i] == '0')
{
// If there is no string
// which ends with '1'
if (endOne.Count == 0)
{
// Push newSeq into endZero
endZero.Add(newSeq);
}
else
{
// Put the last element
// of endOne into newSeq
newSeq = endOne[endOne.Count - 1];
// Remove the last
// element of endOne
endOne.Remove(endOne.Count - 1);
// newSeq ends with '0'
endZero.Add(newSeq);
}
}
else
{
// If there is no string
// which ends with '0'
if (endZero.Count == 0)
{
// Push newSeq into endOne
endOne.Add(newSeq);
}
else
{
// Put the last element
// of endZero into newSeq
newSeq = endZero[endZero.Count - 1];
// Remove the last element of endOne
endZero.Remove(endZero.Count - 1);
// newSeq ends with '1'
endOne.Add(newSeq);
}
}
// Put newSeq into vector ans
ans[i] = newSeq;
}
// Output the minimum
// number of subsequences
Console.WriteLine(endZero.Count + endOne.Count);
// Output the subsequences
// to which each character
// of S belongs to
for (int i = 0; i < N; ++i)
{
// Add 1 as the index starts from 0
Console.Write(ans[i] + 1 + " ");
}
}
// Driver Code
public static void Main()
{
// Given input
String S = "1000110";
int N = 7;
// Function Call
findSeq(S, N);
}
}
// This code is contributed by gfgking.
Javascript
3
1 1 2 3 3 2 2
时间复杂度: O(N)
辅助空间: O(N)