📌  相关文章
📜  最小化翻转以使大小为 K 的子串相同且可替代

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

最小化翻转以使大小为 K 的子串相同且可替代

给定一个长度为N的二进制字符串S ,任务是最小化找到相同长度N的二进制字符串T所需的操作计数,使得:

  • 在一次操作中,允许翻转任何位,即将0转换为1 ,反之亦然。
  • 在二进制字符串T中,选择一个数字K ,这样:
    • N完全可以被K整除,并且
    • T中的前K位是0 ,接下来的K1 ,接下来的K0 ,依此类推。

例子:

方法:该方法基于以下观察:

基于上述观察,请按照以下步骤实施此方法:

  • 找到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)),用于存储所有除数。