最小化给定二进制字符串中设置位与未设置位交换的成本
给定一个大小为N的二进制字符串S ,任务是通过将每个已设置的位与未设置的位交换来找到最小成本,使得在索引i和j处交换位对的成本为abs(j – i) 。
注意:交换位不能交换两次,并且给定二进制字符串中设置位的计数最多为N/2 。
例子:
Input: S = “1010001”
Output: 3
Explanation:
Following the swapping of characters required:
- Swap characters at indices (0, 1) modifies the string to “0110001” and the cost of this operation is |1 – 0| = 1.
- Swap characters at indices (2, 3) modifies the string to “0101001” and the cost of this operation is |2 – 1| = 1.
- Swap characters at indices (6, 7) modifies the string to “0101010” and the cost of this operation is |7 – 6| = 1.
After the above operations, all the set bits is replaced with unset bits and the total cost of operations is 1 + 1 + 1 = 3.
Input: S = “1100”
Output: 4
方法:可以使用动态编程解决给定的问题,方法是将设置和未设置位的索引存储在两个辅助数组中,比如A[]和B[] ,然后找到数组元素A[]与任意数组B[]的元素。请按照以下步骤解决给定的问题:
- 初始化两个数组,比如A[]和B[] ,并在其中存储 set 和 unset 位的索引。
- 初始化一个二维数组, dp[][] ,维度为K*(N – K) ,其中 K 是S中设置位的计数,这样dp[i][j]存储交换第i个数组元素A的最小成本[]与第j个数组元素B[] 。
- 现在,对于每个州,都有两个选择:
- 将第i个数组元素A[]交换到第(j – 1)个数组元素B[]为dp[i][j] = dp[i][j – 1] 。
- 将第(i – 1)个数组元素A[]交换到第(j – 1)个数组元素B[]和第i个数组元素A[]与第 j个数组元素B[] ,此状态可以计算为dp[i][j] = dp[i – 1][j – 1] + abs(A[i] – B[i]) 。
- 现在,选择上述两个选项中的最小值以找到当前状态:
dp[i][j] = min(dp[i][j-1], dp[i-1][j-1] + abs(A[i] – B[j]))
- 完成上述步骤后,打印dp[K][N – K]的值作为结果的最小操作数。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
#define INF 1000000000
// Function to find the minimum cost
// required to swap every set bit with
// an unset bit
int minimumCost(string s)
{
int N = s.length();
// Stores the indices of set and
// unset bits of the string S
vector A, B;
// Traverse the string S
for (int i = 0; i < N; i++) {
// Store the indices
if (s[i] == '1') {
A.push_back(i);
}
else {
B.push_back(i);
}
}
int n1 = A.size();
int n2 = B.size();
// Initialize a dp table of size
// n1*n2
int dp[n1 + 1][n2 + 1];
// Initialize all states to 0
memset(dp, 0, sizeof(dp));
// Set unreachable states to INF
for (int i = 1; i <= n1; i++) {
dp[i][0] = INF;
}
// Fill the dp Table according to
// the given recurrence relation
for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; j++) {
// Update the value of
// dp[i][j]
dp[i][j] = min(
dp[i][j - 1],
dp[i - 1][j - 1]
+ abs(A[i - 1] - B[j - 1]));
}
}
// Return the minimum cost
return dp[n1][n2];
}
// Driver Code
int main()
{
string S = "1010001";
cout << minimumCost(S);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
static final int INF = 1000000000;
// Function to find the minimum cost
// required to swap every set bit with
// an unset bit
static int minimumCost(String s)
{
int N = s.length();
// Stores the indices of set and
// unset bits of the String S
Vector A = new Vector();
Vector B = new Vector();
// Traverse the String S
for (int i = 0; i < N; i++) {
// Store the indices
if (s.charAt(i) == '1') {
A.add(i);
}
else {
B.add(i);
}
}
int n1 = A.size();
int n2 = B.size();
// Initialize a dp table of size
// n1*n2
int [][]dp = new int[n1 + 1][n2 + 1];
// Set unreachable states to INF
for (int i = 1; i <= n1; i++) {
dp[i][0] = INF;
}
// Fill the dp Table according to
// the given recurrence relation
for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; j++) {
// Update the value of
// dp[i][j]
dp[i][j] = Math.min(
dp[i][j - 1],
dp[i - 1][j - 1]
+ Math.abs(A.get(i - 1) - B.get(j - 1)));
}
}
// Return the minimum cost
return dp[n1][n2];
}
// Driver Code
public static void main(String[] args)
{
String S = "1010001";
System.out.print(minimumCost(S));
}
}
// This code is contributed by shikhasingrajput
Python3
# Python program for the above approach
INF = 1000000000;
# Function to find the minimum cost
# required to swap every set bit with
# an unset bit
def minimumCost(s):
N = len(s);
# Stores the indices of set and
# unset bits of the string S
A = []
B = []
# Traverse the string S
for i in range(0, N):
# Store the indices
if (s[i] == "1"):
A.append(i);
else:
B.append(i);
n1 = len(A)
n2 = len(B)
# Initialize a dp table of size
# n1*n2
dp = [[0 for i in range(n2 + 1)] for j in range(n1 + 1)]
# Set unreachable states to INF
for i in range(1, n1 + 1):
dp[i][0] = INF
# Fill the dp Table according to
# the given recurrence relation
for i in range(1, n1 + 1):
for j in range(1, n2 + 1):
# Update the value of
# dp[i][j]
dp[i][j] = min(
dp[i][j - 1],
dp[i - 1][j - 1] + abs(A[i - 1] - B[j - 1])
);
# Return the minimum cost
return dp[n1][n2];
# Driver Code
S = "1010001";
print(minimumCost(S));
# This code is contributed by _saurabh_jaiswal.
C#
// C# program for the above approach
using System;
using System.Collections;
using System.Collections.Generic;
public class Program
{
// Function to find the minimum cost
// required to swap every set bit with
// an unset bit
static int minimumCost(string s)
{
int INF = 1000000000;
int N = s.Length;
// Stores the indices of set and
// unset bits of the string S
List A = new List();
List B = new List();
// Traverse the string S
for (int i = 0; i < N; i++) {
// Store the indices
if (s[i] == '1') {
A.Add(i);
}
else {
B.Add(i);
}
}
int n1 = A.Count;
int n2 = B.Count;
// Initialize a dp table of size
// n1*n2
int [,]dp = new int[n1 + 1,n2 + 1];
// Set unreachable states to INF
for (int i = 1; i <= n1; i++) {
dp[i,0] = INF;
}
// Fill the dp Table according to
// the given recurrence relation
for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; j++) {
// Update the value of
// dp[i][j]
dp[i,j] = Math.Min(
dp[i,j - 1],
dp[i - 1,j - 1]
+ Math.Abs(A[i - 1] - B[j - 1]));
}
}
// Return the minimum cost
return dp[n1,n2];
}
public static void Main()
{
string S = "1010001";
Console.Write(minimumCost(S));
}
}
// This code is contributed by rutvik_56.
Javascript
输出:
3
时间复杂度: O(K*(N – K)) 其中 K 是S中设置位的计数。
辅助空间: O(K*(N – K))