最小化翻转以使大小为 K 的子串相同且可替代
给定一个长度为N的二进制字符串S ,任务是最小化找到相同长度N的二进制字符串T所需的操作计数,使得:
- 在一次操作中,允许翻转任何位,即将0转换为1 ,反之亦然。
- 在二进制字符串T中,选择一个数字K ,这样:
- N完全可以被K整除,并且
- T中的前K位是0 ,接下来的K是1 ,接下来的K是0 ,依此类推。
例子:
Input: S = 1011011
Output: 4
Explanation:
If we choose K = 1, then required string S=0101010, Moves required 4
If we choose K = 7, then required string S=0000000, Moves required 5
Values of K= 2, 3, 4, 5, 6 is not allowed because, it is not perfectly divide N = 7.
Choose K = 1. So, Final String is 0101010, Flip the first, second, third and seventh bit. Print 4 because string S satisfies all conditions after performing 4 moves.
Input: S = 000001
Output: 1
Explanation:
If we choose K=1, then required string S=010101, Moves required 2
If we choose K=2, then required string S=001100, Moves required 3
If we choose K=3, then required string S=000111, Moves required 2
If we choose K=6, then required string S=000000, Moves required 1
So, Select K=6, So, output will be1.
方法:该方法基于以下观察:
It is mentioned in the problem statement itself that we have to choose K such that N is divisible by K, so we can break our problem into subproblem to find all the divisors of N and then find number of operations required for each of the divisor and choose the minimum number of operation between all of them.
基于上述观察,请按照以下步骤实施此方法:
- 找到N 的所有除数(给定字符串的大小)。
- 对于每个除数,遍历字符串和每次迭代:
- 如果我们选择 K = 当前除数,则计算给定字符串中所需的更改次数。
- 如果当前所需的更改少于先前的结果,则使用当前结果对其进行更新。
- 返回所需的最小更改。
下面是上述方法的实现:
C++
// C++ code to implement above approach
#include
using namespace std;
// Function to find all divisors
// of given string length n.
void findAllDivisors(int n, vector& v)
{
for (int i = 1; i <= sqrt(n); i++) {
// Check whether the given number
// is divisible by current number or not
if (n % i == 0) {
// Check if divisors are equal
if (n / i == i)
v.push_back(i);
else {
v.push_back(n / i);
}
}
}
}
// Function to find the minimum
// number of operation require to make
// given substring alternative of size K
int findMinOperations(string& S)
{
int n = S.length(), result = n;
// Find and store all divisors of n.
vector v;
findAllDivisors(n, v);
// For each divisor,
// calculate minimum changes required.
for (int i = 0; i < v.size(); i++) {
// Count of operations required
int count = 0;
bool flag = false;
for (int j = 0; j < n; j += v[i]) {
for (int k = j; k < j + v[i] && k < n; k++) {
if (flag && S[k] == '0')
count++;
if (!flag && S[k] == '1')
count++;
}
flag = (flag == false);
}
// If current changes required
// is less than previous result
// then update result
if (count < result)
result = count;
}
return result;
}
// Driver code
int main()
{
string S = "101101";
cout << findMinOperations(S);
return 0;
}
Java
// Java code to implement above approach
import java.util.*;
class GFG {
// Function to find all divisors
// of given string length n.
static void findAllDivisors(int n, Vector v)
{
for (int i = 1; i <= Math.sqrt(n); i++) {
// Check whether the given number
// is divisible by current number or not
if (n % i == 0) {
// Check if divisors are equal
if (n / i == i)
v.add(i);
else {
v.add(n / i);
}
}
}
}
// Function to find the minimum
// number of operation require to make
// given substring alternative of size K
static int findMinOperations(String S)
{
int n = S.length();
int result = n;
// Find and store all divisors of n.
Vector v = new Vector();
findAllDivisors(n, v);
// For each divisor,
// calculate minimum changes required.
for (int i = 0; i < v.size(); i++) {
// Count of operations required
int count = 0;
boolean flag = false;
for (int j = 0; j < n; j += v.get(i)) {
for (int k = j; k < j + v.get(i) && k < n;
k++) {
if (flag && S.charAt(k) == '0')
count++;
if (!flag && S.charAt(k) == '1')
count++;
}
flag = (flag == false);
}
// If current changes required
// is less than previous result
// then update result
if (count < result)
result = count;
}
return result;
}
// Driver code
public static void main(String[] args)
{
String S = "101101";
System.out.print(findMinOperations(S));
}
}
// This code is contributed by hrithikgarg03188.
Python3
# Python3 program to implement the above approach
# function to find all divisors of
# given string length n
def findAllDivisors(n, v):
for i in range(1, 1 + int(n ** 0.5)):
# check whether the given number
# is divisible by the current number or not
if n % i == 0:
# check if divisors are equal
if (n // i) == i:
v.append(i)
else:
v.append(n // i)
return v
# function to find the minimum
# number of opertations required to make
# given subtring alternative of size K
def findMinOperations(S):
n = len(S)
result = n
# find and store all divisors of n
v = []
v = findAllDivisors(n, v)
for i in range(len(v)):
# count of operations required
count = 0
flag = False
for j in range(0, n, v[i]):
for k in range(j, min(j + v[i], n), 1):
if (flag and S[k]) == "0":
count += 1
if (not flag and S[k]) == "1":
count += 1
flag = bool(flag == False)
# if current changes required
# is less than the previous result,
# then, update the result
if count < result:
result = count
return result
# Driver Code
S = "101101"
print(findMinOperations(S))
# this code was contributed by phasing17
C#
// C# code to implement above approach
using System;
using System.Collections;
public class GFG{
// Function to find all divisors
// of given string length n.
static void findAllDivisors(int n, ArrayList v)
{
for (int i = 1; i <= Math.Sqrt(n); i++) {
// Check whether the given number
// is divisible by current number or not
if (n % i == 0) {
// Check if divisors are equal
if (n / i == i)
v.Add(i);
else {
v.Add(n / i);
}
}
}
}
// Function to find the minimum
// number of operation require to make
// given substring alternative of size K
static int findMinOperations(String S)
{
int n = S.Length;
int result = n;
// Find and store all divisors of n.
ArrayList v = new ArrayList();
findAllDivisors(n, v);
// For each divisor,
// calculate minimum changes required.
for (int i = 0; i < v.Count; i++) {
// Count of operations required
int count = 0;
bool flag = false;
for (int j = 0; j < n; j += (int)v[i]) {
for (int k = j; k < j + (int)v[i] && k < n;
k++) {
if (flag && S[k] == '0')
count++;
if (!flag && S[k] == '1')
count++;
}
flag = (flag == false);
}
// If current changes required
// is less than previous result
// then update result
if (count < result)
result = count;
}
return result;
}
// Driver code
static public void Main (){
string S = "101101";
Console.Write(findMinOperations(S));
}
}
// This code is contributed by hrithikgarg03188.
Javascript
// JavaScript code to implement above approach
// Function to find all divisors
// of given string length n.
function findAllDivisors(n, v)
{
for (var i = 1; i <= Math.floor(Math.sqrt(n)); i++) {
// Check whether the given number
// is divisible by current number or not
if (n % i == 0) {
// Check if divisors are equal
if (Math.floor(n / i) == i)
v.push(i);
else {
v.push(Math.floor(n / i));
}
}
}
return v;
}
// Function to find the minimum
// number of operation require to make
// given substring alternative of size K
function findMinOperations(S)
{
var n = S.length;
var result = n;
// Find and store all divisors of n.
var v = [];
v = findAllDivisors(n, v);
// For each divisor,
// calculate minimum changes required.
for (var i = 0; i < v.length; i++) {
// Count of operations required
var count = 0;
var flag = false;
for (var j = 0; j < n; j += v[i]) {
for (var k = j; k < j + v[i] && k < n; k++) {
if (flag && S[k] == '0')
count++;
if (!flag && S[k] == '1')
count++;
}
flag = (flag == false);
}
// If current changes required
// is less than previous result
// then update result
if (count < result)
result = count;
}
return result;
}
// Driver code
var S = "101101";
document.write(findMinOperations(S));
//This code is contributed by phasing17
3
时间复杂度: O(N*sqrt(N)),O(sqrt(N)) 找到所有除数,O(N) 找到每个除数的所有操作。
辅助空间: O(sqrt(N)),用于存储所有除数。