📌  相关文章
📜  通过翻转除任何 1 之外的所有位,以最少的操作将给定的二进制字符串转换为另一个

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

通过翻转除任何 1 之外的所有位,以最少的操作将给定的二进制字符串转换为另一个

给定两个二进制字符串s1s2 ,任务是计算将字符串s1 转换为 s2的最少操作。在一个操作中,可以选择一个设置位,并且翻转除此之外的所有其他位。如果无法转换 s1-> s2 print -1

例子:

处理方法:可以看出,在两次操作字符串保持原样后,选择相同的索引为 1。所以应该为每个操作选择不同的索引,这样字符串s1 中的“10”可以通过两个操作转换为字符串 s2 中的字符串“ 01” 。所以答案取决于最小化字符串s1 和 s2 中“10”和“01”的数量。如果在任何索引处“0(s1) – 1(s2)” && “1(s1) – 0(s2)”数量相等,则答案为 else -1。

请按照以下步骤解决此问题:

  • 初始化变量res = INT_MAX
  • 初始化变量ops1= -1以存储将字符串s1 转换为 s2所需的操作,无需任何修改。
  • 现在检查是否可以通过在(1(s1)-> 1(s2))的情况下进行 1 次初始修改来最小化操作。
  • 将操作存储在ops2变量中,并通过执行min(res,ops2)将最小值存储在res中。
  • 现在检查是否可以通过在(1(s1)-> 0(s2))的情况下进行 1 次初始修改来最小化操作。
  • 将操作存储在ops3变量中,并通过执行min(res,ops3)将最小值存储在res中。
  • 如果res等于INT_MAX ,则意味着无法转换字符串s1 -> s2 所以打印 -1。
  • 否则打印res

下面是上述方法的实现:

C++14
// C++ program for the above approach
#include 
using namespace std;
 
// Function to count the "0(s1)-1(s2)"
// && "1(s1)- 0(s2)" pairs
int count_operations(string s1, string s2)
{
    int n = s1.size();
     
    // Initializing to 0 initially
    int cnt10 = 0, cnt01 = 0;
    for (int i = 0; i < n; i++) {
        if (s1[i] != s2[i]) {
            if (s1[i] == '0')
                cnt01++;
            else
                cnt10++;
        }
    }
     
    // Equal 0(s1)-1(s2) and 1(s1)- 0(s2) pairs
    // To convert 1 pair 2 operations are required
    // so 2 * cnt01
    if (cnt01 == cnt10)
        return 2 * cnt01;
    return -1;
}
 
// Function to do one operation of
// modifying the string s1
bool modify_string(string& s1, string& s2,
                   char c)
{
    int n = s1.size();
    int idx = -1;
     
    // Find the index of occurrence of
    // 1(s1)- c(s2) in s1
    for (int i = 0; i < n; i++) {
        if (s1[i] == '1' && s2[i] == c) {
             
            // Break if found
            idx = i;
            break;
        }
    }
    if (idx == -1)
        return 0;
     
    // Flip the remaining except that index
    for (int i = 0; i < n; i++) {
        if (i == idx)
            continue;
        if (s1[i] == '1')
            s1[i] = '0';
        else
            s1[i] = '1';
    }
    return 1;
}
 
// Function to find the minimum operations
// to convert the string s1 to string s2
int find_min_operations(string s1, string s2)
{
    int res = INT_MAX;
     
    // Case -1 Initial strings itself
    int ops1 = count_operations(s1, s2);
   
    if (ops1 != -1)
        res = min(res, ops1);
 
    string a = s1, b = s2;
     
    // Case -2 Doing 1 modification initially
    // for 1(s1)-1(s2)
    if (modify_string(a, b, '1')) {
   
        int ops2 = count_operations(a, b);
         
        // Take minimum
        if (ops2 != -1)
            res = min(res, 1 + ops2);
        
    }
  
 
    // Case-3 doing 1 modification initially
    // for 1(s1) - 0(s2)
    a = s1, b = s2;
    if (modify_string(a, b, '0')) {
        int ops3 = count_operations(a, b);
         
        // Take minimum
        if (ops3 != -1)
            res = min(res, 1 + ops3);
    }
 
    if (res == INT_MAX)
        return -1;
    else
        return res;
}
 
// Driver code
int main()
{
    string s1 = "100010111";
    string s2 = "101101100";
     
    // Function call
    cout << find_min_operations(s1, s2) << endl;
    return 0;
}


Python3
# Python program for the above approach
INT_MAX = 2147483647;
 
# Function to count the "0(s1)-1(s2)"
# && "1(s1)- 0(s2)" pairs
def count_operations (s1, s2):
    n = len(s1);
 
    # Initializing to 0 initially
    cnt10 = 0
    cnt01 = 0;
    for i in range(n):
        if (s1[i] != s2[i]):
            if (s1[i] == '0'):
                cnt01 += 1
            else:
                cnt10 += 1
 
    # Equal 0(s1)-1(s2) and 1(s1)- 0(s2) pairs
    # To convert 1 pair 2 operations are required
    # so 2 * cnt01
    if (cnt01 == cnt10):
        return 2 * cnt01;
    return -1;
 
# Function to do one operation of
# modifying the let s1
def modify_string (s1, s2, c):
    n = len(s1);
    idx = -1;
 
    # Find the index of occurrence of
    # 1(s1)- c(s2) in s1
    for i in range(n):
        if (s1[i] == '1' and s2[i] == c):
 
            # Break if found
            idx = i;
            break;
    if (idx == -1):
        return 0;
 
    # Flip the remaining except that index
    for i in range(n):
        if (i == idx):
            continue;
        if (s1[i] == '1'):
            s1[i] = '0';
        else:
            s1[i] = '1';
    return 1;
 
 
# Function to find the minimum operations
# to convert the let s1 to let s2
def find_min_operations (s1, s2):
    res = 10 ** 9;
 
    # Case -1 Initial strings itself
    ops1 = count_operations(s1, s2);
    if (ops1 != -1):
        res = min(res, ops1);
 
    a = s1
    b = s2;
    # Case -2 Doing 1 modification initially
    # for 1(s1)-1(s2)
    if (modify_string(a, b, '1')):
        ops2 = count_operations(a, b);
 
        # Take minimum
        if (ops2 != -1):
            res = min(res, 1 + ops2);
 
    # Case-3 doing 1 modification initially
    # for 1(s1) - 0(s2)
    a = s1
    b = s2;
    if (modify_string(a, b, '0')):
        ops3 = count_operations(a, b);
 
        # Take minimum
        if (ops3 != -1):
            res = min(res, 1 + ops3);
 
    if (res == 10 ** 9):
        return -1;
    else:
        return res;
 
 
# Driver code
s1 = "100010111";
s2 = "101101100";
s1 = list(s1);
s2 = list(s2);
 
# Function call
print(find_min_operations(s1, s2));
 
# This code is contributed by gfgking


C#
// C# program for the above approach
using System;
class GFG {
 
  // Function to count the "0(s1)-1(s2)"
  // && "1(s1)- 0(s2)" pairs
  static int count_operations(string s1, string s2)
  {
    int n = s1.Length;
 
    // Initializing to 0 initially
    int cnt10 = 0, cnt01 = 0;
    for (int i = 0; i < n; i++) {
      if (s1[i] != s2[i]) {
        if (s1[i] == '0')
          cnt01++;
        else
          cnt10++;
      }
    }
 
    // Equal 0(s1)-1(s2) and 1(s1)- 0(s2) pairs
    // To convert 1 pair 2 operations are required
    // so 2 * cnt01
    if (cnt01 == cnt10)
      return 2 * cnt01;
    return -1;
  }
 
  // Function to do one operation of
  // modifying the string s1
  static int modify_string(ref string s1, ref string s2,
                           char c)
  {
    int n = s1.Length;
    char[] str1 = s1.ToCharArray();
    char[] str2 = s2.ToCharArray();
 
    int idx = -1;
 
    // Find the index of occurrence of
    // 1(s1)- c(s2) in s1
    for (int i = 0; i < n; i++) {
      if (str1[i] == '1' && str2[i] == c) {
 
        // Break if found
        idx = i;
        break;
      }
    }
    if (idx == -1)
      return 0;
 
    // Flip the remaining except that index
    for (int i = 0; i < n; i++) {
      if (i == idx)
        continue;
      if (str1[i] == '1')
        str1[i] = '0';
      else
        str1[i] = '1';
    }
    s1 = new string(str1);
    s2 = new string(str2);
    return 1;
  }
 
  // Function to find the minimum operations
  // to convert the string s1 to string s2
  static int find_min_operations(string s1, string s2)
  {
    int res = Int32.MaxValue;
 
    // Case -1 Initial strings itself
    int ops1 = count_operations(s1, s2);
 
    if (ops1 != -1)
      res = Math.Min(res, ops1);
 
    string a = s1, b = s2;
 
    // Case -2 Doing 1 modification initially
    // for 1(s1)-1(s2)
    if (modify_string(ref a, ref b, '1') > 0) {
      int ops2 = count_operations(a, b);
 
      // Take minimum
      if (ops2 != -1)
        res = Math.Min(res, 1 + ops2);
    }
 
    // Case-3 doing 1 modification initially
    // for 1(s1) - 0(s2)
    a = s1;
    b = s2;
    if (modify_string(ref a, ref b, '0') > 0) {
      int ops3 = count_operations(a, b);
 
      // Take minimum
      if (ops3 != -1)
        res = Math.Min(res, 1 + ops3);
    }
 
    if (res == Int32.MaxValue)
      return -1;
    else
      return res;
  }
 
  // Driver code
  public static void Main()
  {
    string s1 = "100010111";
    string s2 = "101101100";
 
    // Function call
    Console.WriteLine(find_min_operations(s1, s2));
  }
}
 
// This code is contributed by ukasp.


Javascript


Java
// Java program for the above approach
import java.util.*;
public class GFG {
 
  // Function to count the "0(s1)-1(s2)"
  // && "1(s1)- 0(s2)" pairs
  static int count_operations(String s1, String s2)
  {
    int n = s1.length();
 
    // Initializing to 0 initially
    int cnt10 = 0, cnt01 = 0;
    for (int i = 0; i < n; i++) {
      if (s1.charAt(i) != s2.charAt(i)) {
        if (s1.charAt(i) == '0')
          cnt01++;
        else
          cnt10++;
      }
    }
 
    // Equal 0(s1)-1(s2) and 1(s1)- 0(s2) pairs
    // To convert 1 pair 2 operations are required
    // so 2 * cnt01
    if (cnt01 == cnt10)
      return 2 * cnt01;
    return -1;
  }
 
  // Function to do one operation of
  // modifying the string s1
  static int modify_string(String s1, String s2,
                           char c)
  {
    int n = s1.length();
    char[] str1 = s1.toCharArray();
    char[] str2 = s2.toCharArray();
 
    int idx = -1;
 
    // Find the index of occurrence of
    // 1(s1)- c(s2) in s1
    for (int i = 0; i < n; i++) {
      if (str1[i] == '1' && str2[i] == c) {
 
        // Break if found
        idx = i;
        break;
      }
    }
    if (idx == -1)
      return 0;
 
    // Flip the remaining except that index
    for (int i = 0; i < n; i++) {
      if (i == idx)
        continue;
      if (str1[i] == '1')
        str1[i] = '0';
      else
        str1[i] = '1';
    }
    s1 = new String(str1);
    s2 = new String(str2);
    return 1;
  }
 
  // Function to find the minimum operations
  // to convert the string s1 to string s2
  static int find_min_operations(String s1, String s2)
  {
    int res = Integer.MAX_VALUE;
 
    // Case -1 Initial strings itself
    int ops1 = count_operations(s1, s2);
    ops1 /= 2;
     
    if (ops1 != -1)
      res = Math.min(res, ops1);
 
    String a = s1, b = s2;
 
    // Case -2 Doing 1 modification initially
    // for 1(s1)-1(s2)
    if (modify_string(a, b, '1') > 0) {
      int ops2 = count_operations(a, b);
 
      // Take minimum
      if (ops2 != -1)
        res = Math.min(res, 1 + ops2);
    }
 
    // Case-3 doing 1 modification initially
    // for 1(s1) - 0(s2)
    a = s1;
    b = s2;
    if (modify_string(a, b, '0') > 0) {
      int ops3 = count_operations(a, b);
 
      // Take minimum
      if (ops3 != -1)
        res = Math.min(res, 1 + ops3);
    }
 
    if (res == Integer.MAX_VALUE)
      return -1;
    else
      return res;
  }
 
  // Driver code
  public static void main(String args[])
  {
    String s1 = "100010111";
    String s2 = "101101100";
 
    // Function call
    System.out.println(find_min_operations(s1, s2));
  }
}
 
// This code is contributed by Samim Hossain Mondal.



输出
3

时间复杂度: O(N) 其中 N 是字符串的长度。
空间复杂度: O(N)