Change Minimum Characters to Satisfy One of Three Conditions
You are given two strings a and b that consist of lowercase letters. In one operation, you can change any character in a or b to any lowercase letter.
Your goal is to satisfy one of the following three conditions:
Every letter in a is strictly less than every letter in b in the alphabet.
Every letter in b is strictly less than every letter in a in the alphabet.
Both a and b consist of only one distinct letter.
Return the minimum number of operations needed to achieve your goal.
Example 1:
Input: a = "aba", b = "caa"
Output: 2
Explanation: Consider the best way to make each condition true:
1) Change b to "ccc" in 2 operations, then every letter in a is less than every letter in b.
2) Change a to "bbb" and b to "aaa" in 3 operations, then every letter in b is less than every letter in a.
3) Change a to "aaa" and b to "aaa" in 2 operations, then a and b consist of one distinct letter.
The best way was done in 2 operations (either condition 1 or condition 3).
Example 2:
Input: a = "dabadd", b = "cda"
Output: 3
Explanation: The best way is to make condition 1 true by changing b to "eee".
Constraints:
1 <= a.length, b.length <= 105
a and b consist only of lowercase letters.
Solution:
option3 is trivial to calculate for option1 and 2, first calculate countmaps for both strings, for example, if a = "aba", b = "caa", then we have [2 1 0] [2 0 1] calculate prefix sum on both coutmaps, we get - a b c [0 2 3 3] [0 2 2 3] to make a smaller than b, we can pick one pivot char in a, and make all chars in a small or equal to the pivot, and make all chars in b greater than the pivot, if we pick char a as the pivot for example, the number of ops to make all chars in a <= a is prefix[-1] - prefix[1] (which is a) = 3 - 2 = 1 the number of ops to make all chars in b > a is prefix[1] = 2 so the total number of operations is 1 + 2 = 3 if we pick char b is pivot, then ops to make all chars in a <= b is 3 - 3 = 0 ops to make all chars in c > b = 2 total number ops is 2 if we pick char c, then in a, <= c is 0 > c = 3 total is 3, so for option1, we have min of 2
we can calculate option2 with same method
class Solution {
public int minCharacters(String a, String b) {
int[] counta = new int[26];
int[] countb = new int[26];
int m = a.length(), n = b.length();
int maxa = 0, maxb = 0;
for (int i = 0; i < m; i ++) {
counta[a.charAt(i) - 'a'] ++;
maxa = Math.max(maxa, counta[a.charAt(i) - 'a']);
}
for (int i = 0; i < n; i ++) {
countb[b.charAt(i) - 'a'] ++;
maxb = Math.max(maxb, countb[b.charAt(i) - 'a']);
}
// a: [2, 1, 0]
// [0 2 3 3]
// b: [2, 0, 1]
// [0 2 2 3]
//
// a: [2 1 0 3]
// 0 2 3 3 6
// b: [1 0 1 1]
// 0 1 1 2 3
int option1 = makeASmaller(counta, countb);
int option2 = makeASmaller(countb, counta);
int option3 = m - maxa + n - maxb;
// System.out.println(Arrays.asList(option1, option2, option3));
return Math.min(option1, Math.min(option2, option3));
// return option1;
}
private int makeASmaller(int[] a, int [] b) {
int[] prefixa = new int[27];
int[] prefixb = new int[27];
for (int i = 1; i < 27; i ++) {
prefixa[i] = prefixa[i - 1] + a[i - 1];
prefixb[i] = prefixb[i - 1] + b[i - 1];
}
int res = 1000000;
// System.out.println(Arrays.toString(prefixa));
// System.out.println(Arrays.toString(prefixb));
for (int i = 1; i < 26; i ++) {
int incB = prefixb[i];
int decA = prefixa[26] - prefixa[i];
// System.out.println(i + ", " + incB + ", " + decA);
res = Math.min(res, incB + decA);
}
return res;
}
}