Welcome to Subscribe On Youtube
2896. Apply Operations to Make Two Strings Equal
Description
You are given two 0-indexed binary strings s1
and s2
, both of length n
, and a positive integer x
.
You can perform any of the following operations on the string s1
any number of times:
- Choose two indices
i
andj
, and flip boths1[i]
ands1[j]
. The cost of this operation isx
. - Choose an index
i
such thati < n - 1
and flip boths1[i]
ands1[i + 1]
. The cost of this operation is1
.
Return the minimum cost needed to make the strings s1
and s2
equal, or return -1
if it is impossible.
Note that flipping a character means changing it from 0
to 1
or vice-versa.
Example 1:
Input: s1 = "1100011000", s2 = "0101001010", x = 2 Output: 4 Explanation: We can do the following operations: - Choose i = 3 and apply the second operation. The resulting string is s1 = "1101111000". - Choose i = 4 and apply the second operation. The resulting string is s1 = "1101001000". - Choose i = 0 and j = 8 and apply the first operation. The resulting string is s1 = "0101001010" = s2. The total cost is 1 + 1 + 2 = 4. It can be shown that it is the minimum cost possible.
Example 2:
Input: s1 = "10110", s2 = "00011", x = 4 Output: -1 Explanation: It is not possible to make the two strings equal.
Constraints:
n == s1.length == s2.length
1 <= n, x <= 500
s1
ands2
consist only of the characters'0'
and'1'
.
Solutions
Solution 1: Memoization
We notice that since each operation reverses two characters, if the number of different characters in the two strings is odd, it is impossible to make them equal, and we directly return
Next, we design a function
The calculation process of the function
If
Otherwise, we consider the two endpoints of the interval
- If we perform the first operation on endpoint
, since the costi is fixed, the optimal choice is to reversex andidx[i] , and then recursively calculateidx[j] , with a total cost ofdfs(i+1,j−1) .dfs(i+1,j−1)+x - If we perform the second operation on endpoint
, we need to reverse all the characters ini , and then recursively calculate[idx[i]..idx[i+1]] , with a total cost ofdfs(i+2,j) .dfs(i+2,j)+idx[i+1]−idx[i] - If we perform the second operation on endpoint
, we need to reverse all the characters inj , and then recursively calculate[idx[j−1]..idx[j]] , with a total cost ofdfs(i,j−2) .dfs(i,j−2)+idx[j]−idx[j−1]
We take the minimum value of the above three operations as the value of
To avoid redundant calculations, we can use memoization to record the return value of
The time complexity is
-
class Solution { private List<Integer> idx = new ArrayList<>(); private Integer[][] f; private int x; public int minOperations(String s1, String s2, int x) { int n = s1.length(); for (int i = 0; i < n; ++i) { if (s1.charAt(i) != s2.charAt(i)) { idx.add(i); } } int m = idx.size(); if (m % 2 == 1) { return -1; } this.x = x; f = new Integer[m][m]; return dfs(0, m - 1); } private int dfs(int i, int j) { if (i > j) { return 0; } if (f[i][j] != null) { return f[i][j]; } f[i][j] = dfs(i + 1, j - 1) + x; f[i][j] = Math.min(f[i][j], dfs(i + 2, j) + idx.get(i + 1) - idx.get(i)); f[i][j] = Math.min(f[i][j], dfs(i, j - 2) + idx.get(j) - idx.get(j - 1)); return f[i][j]; } }
-
class Solution { public: int minOperations(string s1, string s2, int x) { vector<int> idx; for (int i = 0; i < s1.size(); ++i) { if (s1[i] != s2[i]) { idx.push_back(i); } } int m = idx.size(); if (m & 1) { return -1; } if (m == 0) { return 0; } int f[m][m]; memset(f, -1, sizeof(f)); function<int(int, int)> dfs = [&](int i, int j) { if (i > j) { return 0; } if (f[i][j] != -1) { return f[i][j]; } f[i][j] = min({dfs(i + 1, j - 1) + x, dfs(i + 2, j) + idx[i + 1] - idx[i], dfs(i, j - 2) + idx[j] - idx[j - 1]}); return f[i][j]; }; return dfs(0, m - 1); } };
-
class Solution: def minOperations(self, s1: str, s2: str, x: int) -> int: @cache def dfs(i: int, j: int) -> int: if i > j: return 0 a = dfs(i + 1, j - 1) + x b = dfs(i + 2, j) + idx[i + 1] - idx[i] c = dfs(i, j - 2) + idx[j] - idx[j - 1] return min(a, b, c) n = len(s1) idx = [i for i in range(n) if s1[i] != s2[i]] m = len(idx) if m & 1: return -1 return dfs(0, m - 1)
-
func minOperations(s1 string, s2 string, x int) int { idx := []int{} for i := range s1 { if s1[i] != s2[i] { idx = append(idx, i) } } m := len(idx) if m&1 == 1 { return -1 } f := make([][]int, m) for i := range f { f[i] = make([]int, m) for j := range f[i] { f[i][j] = -1 } } var dfs func(i, j int) int dfs = func(i, j int) int { if i > j { return 0 } if f[i][j] != -1 { return f[i][j] } f[i][j] = dfs(i+1, j-1) + x f[i][j] = min(f[i][j], dfs(i+2, j)+idx[i+1]-idx[i]) f[i][j] = min(f[i][j], dfs(i, j-2)+idx[j]-idx[j-1]) return f[i][j] } return dfs(0, m-1) }
-
function minOperations(s1: string, s2: string, x: number): number { const idx: number[] = []; for (let i = 0; i < s1.length; ++i) { if (s1[i] !== s2[i]) { idx.push(i); } } const m = idx.length; if (m % 2 === 1) { return -1; } if (m === 0) { return 0; } const f: number[][] = Array.from({ length: m }, () => Array.from({ length: m }, () => -1)); const dfs = (i: number, j: number): number => { if (i > j) { return 0; } if (f[i][j] !== -1) { return f[i][j]; } f[i][j] = dfs(i + 1, j - 1) + x; f[i][j] = Math.min(f[i][j], dfs(i + 2, j) + idx[i + 1] - idx[i]); f[i][j] = Math.min(f[i][j], dfs(i, j - 2) + idx[j] - idx[j - 1]); return f[i][j]; }; return dfs(0, m - 1); }