Open azl397985856 opened 2 years ago
Count and simulation.
step1: count frequency of letter in a and b.
step2: Enumerate every condition and find the min.
Enumerate a-z to meet the condition .
Enumerate a-z to meet the condition 1 and 2(symmetrical) .
for one letter x, every letter in a is less than or equal to x, every letter in b is greater than x
class Solution {
public int minCharacters(String a, String b) {
int[] acount = new int[26];
int[] bcount = new int[26];
for (char ch : a.toCharArray()) {
acount[ch - 'a']++;
}
for (char ch : b.toCharArray()) {
bcount[ch - 'a']++;
}
//third condition (calculate every possible character)
int ans = a.length() + b.length();
for (int i = 0; i < 26; i++) {
ans = Math.min(ans, a.length() + b.length() - acount[i] - bcount[i]);
}
//first and second contion(symmetrical)
ans = Math.min(ans, Math.min(smaller(acount, bcount), smaller(bcount, acount)));
return ans;
}
// return minimum operations which can make every letter in a is less than every letter in b. private int smaller(int[] a, int[] b) { int res = Integer.MAX_VALUE; for (int i = 0; i < 25; i++) { int total = 0; for (int j = i + 1; j < 26; j++) { total += a[j]; } for (int k = 0; k <= i; k++) { total += b[k]; } res = Math.min(res, total); } return res; } }
### Complexity
time=O(m + n) space=O(26)
题目没看太懂。。。
class Solution {
public:
int minCharacters(string a, string b) {
int m = a.size(), n = b.size(), res = m + n;
vector<int> c1(26), c2(26);
for (char& c : a) c1[c - 'a']++;
for (char& c : b) c2[c - 'a']++;
for (int i = 0; i < 26; ++i) {
res = min(res, m + n - c1[i] - c2[i]); // condition 3
if (i > 0) {
c1[i] += c1[i - 1];
c2[i] += c2[i - 1];
}
if (i < 25) {
res = min(res, m - c1[i] + c2[i]); // condition 1
res = min(res, n - c2[i] + c1[i]); // condition 2
}
}
return res;
}
};
O(n)+O(1)
class Solution {
public int minCharacters(String a, String b) {
int[] arrA = new int[26];
int[] arrB = new int[26];
int lenA = a.length(), lenB = b.length();
for(char c : a.toCharArray()){
arrA[c-'a']++;
}
for(char c : b.toCharArray()){
arrB[c-'a']++;
}
int res = Integer.MAX_VALUE;
int cond12 = Integer.MAX_VALUE;
int cond3 = Integer.MAX_VALUE;
int sumA = 0, sumB = 0;
for(int i = 0; i < 25; i++){
sumA += arrA[i];
sumB += arrB[i];
cond3 = Math.min(res, lenA-arrA[i]+lenB-arrB[i]);
cond12 = Math.min(lenA-sumA+sumB, lenB-sumB+sumA);
res = Math.min(cond3, cond12);
}
res = Math.min(res, lenA-arrA[25]+lenB-arrB[25]);
return res;
}
}
class Solution {
public int minCharacters(String a, String b) {
int len1 = a.length(), len2 = b.length(), result = len1+len2;
int[] countA = new int[26];
for(int i=0;i<len1;i++)
countA[a.charAt(i)-'a']++;
int[] countB = new int[26];
for(int i=0;i<len2;i++)
countB[b.charAt(i)-'a']++;
int cur1 = 0, cur2 = 0, maxCount = countA[25]+countB[25];
for(int i=0;i<25;i++){
cur1+=countA[i];
cur2+=countB[i];
result=Math.min(result,cur1+len2-cur2);
result=Math.min(result,cur2+len1-cur1);
maxCount=Math.max(maxCount,countA[i]+countB[i]);
}
result = Math.min(result,len1+len2-maxCount);
return result;
}
}
Language: Java
public int minCharacters(String a, String b) {
int result = a.length() + b.length();
for (int i = 0; i < 26; i++) {
int count1 = 0, count2 = 0, count3 = 0;
char c = (char) ('a' + i);
for (char x : a.toCharArray()) {
// condition 1, let c be the greatest letter in a
if (x > c) count1++;
// condition 2, let c be the smallest letter in a
if (x < c) count2++;
// condition 3, let c be the only letter in a and b
if (x != c) count3++;
}
for (char x : b.toCharArray()) {
// condition 1
if ( x <= c ) count1++;
// condition 2
if (x >= c) count2++;
// condition 3
if (x != c) count3++;
}
if (i == 0) count2 = Integer.MAX_VALUE;
if (i == 25) count1 = Integer.MAX_VALUE;
result = Math.min(result, Math.min(Math.min(count1, count2), count3));
}
return result;
}
Python3 Code:
class Solution:
def aGreaterb(self,a,b):
counter_a = collections.Counter(a)
counter_b = collections.Counter(b)
ans = float('inf')
# 循环25次 是因为一共只有25个间隔
for i in range(1,26):
count = 0
for j in range(i):
count += counter_a[chr(97+j)]
for j in range(i,26):
count += counter_b[chr(97+j)]
ans = min(ans,count)
return ans
def minCharacters(self, a: str, b: str) -> int:
"""
有三种方案,需要分别执行三种方案,并且记录最小操作数
分别对字符串进行排序
"""
# 考虑需要两个字符串是相同的
total_char = len(a)+len(b)
ans3 = total_char - collections.Counter(a+b).most_common()[0][1]
# 按照字母进行划分 比如说,比较a,b字符串中分别计算大于等于字符'a'和小于字符'a'的个数 那么就是知道了修改次数
return min(self.aGreaterb(a,b),self.aGreaterb(b,a),ans3)
复杂度分析
令 n、m为字符串a,b长度。
···js
/**
看了题解,才有的思路。将问题转化成找到一个基准字母,a中的所有字母小于它,b中的所有字母大于等于它,那么就可以用枚举结果(只有26个字母)的方式,找到需要改变的数量。
class Solution {
public int minCharacters(String a, String b) {
HashMap<Character, Integer> mapA = new HashMap<>();
HashMap<Character, Integer> mapB = new HashMap<>();
for (int i = 0; i < a.length(); i++) {
char c = a.charAt(i);
mapA.put(c, mapA.getOrDefault(c, 0) + 1);
}
for (int i = 0; i < b.length(); i++) {
char c = b.charAt(i);
mapB.put(c, mapB.getOrDefault(c, 0) + 1);
}
int minNum = Integer.MAX_VALUE;
for (int i = 1; i < 26; i++) {
char base = (char) ('a' + i);
// System.out.println("char:" + base);
minNum = Math.min(minNum, oneOrTwo(mapA, mapB, base));
minNum = Math.min(minNum, oneOrTwo(mapB, mapA, base));
}
minNum = Math.min(minNum, three(mapA, mapB));
return minNum;
}
private int oneOrTwo(HashMap<Character, Integer> a, HashMap<Character, Integer> b, char base) {
int num = 0;
for (char c : a.keySet()) {
if (c >= base) {
num += a.get(c);
}
}
for (char c : b.keySet()) {
if (c < base) {
num += b.get(c);
}
}
// System.out.println(num);
return num;
}
private int three(HashMap<Character, Integer> a, HashMap<Character, Integer> b) {
int num = 0;
char base = '0';
int maxNums = Integer.MIN_VALUE;
for (char c : a.keySet()) {
if (maxNums < a.get(c) + b.getOrDefault(c, 0)) {
base = c;
maxNums = a.get(c) + b.getOrDefault(c, 0);
}
}
for (char c : b.keySet()) {
if (a.get(c) == null) {
if (maxNums < b.get(c)) {
base = c;
maxNums = b.get(c);
}
}
}
for (char c : a.keySet()) {
if (c != base) {
num += a.get(c);
}
}
for (char c : b.keySet()) {
if (c != base) {
num += b.get(c);
}
}
// System.out.println(num);
return num;
}
}
class Solution {
public static int minCharacters(String a, String b) {
// 初始化数组用于存储字符串a和b中的字母;
int[] acnt = new int[26];
int[] bcnt = new int[26];
// 获取a和b的字母总数;
int an = a.length(), bn = b.length();
// 分别对字符串的字母计数;
for (char c : a.toCharArray()) {
acnt[c - 'a']++;
}
for (char c : b.toCharArray()) {
bcnt[c - 'a']++;
}
// 遍历两段字母表计算“最少操作数”;
int ans = Integer.MAX_VALUE, ans_1, ans_2, asum = 0, bsum = 0;
for (int i = 0; i < 25; i++) {
// 计算两段字母表的前缀和;
asum += acnt[i];
bsum += bcnt[i];
// 满足条件1或条件2的操作数:操作a的字母均小于等于字母i,操作b的字母均大于字母i,或者反之;
// 注意不能计算字母为‘z’的情况,举例字符串是"a"和"aazz"
ans_1 = Math.min(an - asum + bsum, bn - bsum + asum);
// 满足条件3的操作数:操作a和b中字母i以外的字母,令均转为i;
ans_2 = Math.min(ans, an - acnt[i] + bn - bcnt[i]);
// 贪心策略:比较保留当前的最少操作数;
ans = Math.min(ans_1, ans_2);
}
// 计算条件3在字母为‘z’时的操作数,并比较;
ans = Math.min(ans, an - acnt[25] + bn - bcnt[25]);
return ans;
}
}
class Solution:
def minCharacters(self, a: str, b: str) -> int:
counter1,counter2 = [0]*26,[0]*26
for i in a:
counter1[ord(i)-ord('a')] += 1
for i in b:
counter2[ord(i)-ord('a')] += 1
cod1,cod2,cod3 = float('inf'),float('inf'),float('inf')
for i in range(1,26):
cod1 = min(sum(counter1[i:]) + sum(counter2[:i]), cod1)
cod2 = min(sum(counter2[i:]) + sum(counter1[:i]), cod2)
cod3 = min(len(a)+len(b)-counter1[i]-counter2[i], cod3)
cod3 = min(len(a)+len(b)-counter1[0]-counter2[0],cod3)
return min(cod1,cod2,cod3)
class Solution {
public:
int minCharacters(string a, string b) {
vector<int> acount(26,0);
vector<int> bcount(26,0);
int an=a.size(), bn=b.size();
//统计a b字符频率
for(char c : a) acount[c-'a']++;
for(char c : b) bcount[c-'a']++;
int ans=INT_MAX, asum=0, bsum=0;
for(int i=0;i<25;i++){
asum += acount[i];
bsum += bcount[i];
ans = min(min(ans,an-acount[i]+bn-bcount[i]), min(an-asum+bsum,bn-bsum+asum));
}
ans= min(ans,an-acount[25]+bn-bcount[25]);
return ans;
}
};
https://leetcode-cn.com/problems/change-minimum-characters-to-satisfy-one-of-three-conditions/
给你两个字符串 a 和 b ,二者均由小写字母组成。一步操作中,你可以将 a 或 b 中的 任一字符 改变为 任一小写字母 。
操作的最终目标是满足下列三个条件 之一 :
a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母 。
b 中的 每个字母 在字母表中 严格小于 a 中的 每个字母 。
a 和 b 都 由 同一个 字母组成。
返回达成目标所需的 最少 操作数。
示例 1:
输入:a = "aba", b = "caa"
输出:2
解释:满足每个条件的最佳方案分别是:
1) 将 b 变为 "ccc",2 次操作,满足 a 中的每个字母都小于 b 中的每个字母;
2) 将 a 变为 "bbb" 并将 b 变为 "aaa",3 次操作,满足 b 中的每个字母都小于 a 中的每个字母;
3) 将 a 变为 "aaa" 并将 b 变为 "aaa",2 次操作,满足 a 和 b 由同一个字母组成。
最佳的方案只需要 2 次操作(满足条件 1 或者条件 3)。
示例 2:
输入:a = "dabadd", b = "cda"
输出:3
解释:满足条件 1 的最佳方案是将 b 变为 "eee" 。
提示:
1 <= a.length, b.length <= 105
a 和 b 只由小写字母组成
JavaScript Code:
/**
* @param {string} a
* @param {string} b
* @return {number}
*/
var minCharacters = function(a, b) {
let da = new Array(26).fill(0);
let db = new Array(26).fill(0);
for(let i in a) {
da[a.charCodeAt(i) - 97]++;
}
for(let i in b) {
db[b.charCodeAt(i) - 97]++;
}
let an = a.length, bn = b.length, asum = 0, bsum = 0, res = Number.MAX_SAFE_INTEGER;
for(let i = 0 ; i < 25 ; i++) {
// 前缀和计算
asum += da[i];
bsum += db[i];
// 找最小值
res = Math.min(res, an+bn-da[i]-db[i], an-asum+bsum, bn-bsum+asum);
}
// z的特殊处理
return Math.min(res, an+bn-da[25]-db[25]);
};
复杂度分析
先转化为26个字符的数组,然后对每个字符的数量进行判断,第三个条件就是两个总长度减去当前数量的长度。第一二个条件就是将比当前数字小的a数组都放在小的或者都放在大的需要调整的次数,还需要用到累加。前缀和。
class Solution:
def minCharacters(self, a: str, b: str) -> int:
a_n, b_n = len(a), len(b)
a_arr = [0]*26
b_arr = [0]*26
res = float('inf')
for char in a:
a_arr[ord(char)-ord('a')] += 1
for char in b:
b_arr[ord(char)-ord('a')] += 1
for i in range(26):
res = min(res, a_n+b_n-a_arr[i]-b_arr[i])
if i > 0:
a_arr[i] += a_arr[i-1]
b_arr[i] += b_arr[i-1]
if i < 25:
res = min(res, a_n-a_arr[i]+b_arr[i])
res = min(res, b_n-b_arr[i]+a_arr[i])
return res
时间复杂度On 空间复杂度On
class Solution {
public:
int minCharacters(string a, string b) {
int n = a.size(), m = b.size();
vector<int> stra(26, 0), strb(26, 0);
for(auto c : a) stra[c - 'a'] ++;
for(auto c : b) strb[c - 'a'] ++;
int res = INT_MAX;
int presum1 = 0, presum2 = 0;
for(int i = 0; i < 25; i ++) {
presum1 += stra[i];
presum2 += strb[i];
res = min(min(res, n - presum1 + presum2), min(m - presum2 + presum1, n - stra[i] + m - strb[i]));
}
res = min(res, n - stra[25] + m - strb[25]);
return res;
}
};
思路
代码
class Solution:
def minCharacters(self, A: str, B: str) -> int:
counter_A = [0] * 26
counter_B = [0] * 26
for a in A:
counter_A[ord(a) - ord('a')] += 1
for b in B:
counter_B[ord(b) - ord('a')] += 1
ans = len(A) + len(B)
for i in range(26):
ans = min(ans, len(A) + len(B) - counter_A[i] - counter_B[i])
for i in range(1, 26):
t = 0
for j in range(i, 26):
t += counter_A[j]
for j in range(i):
t += counter_B[j]
ans = min(ans, t)
for i in range(1, 26):
t = 0
for j in range(i, 26):
t += counter_B[j]
for j in range(i):
t += counter_A[j]
ans = min(ans, t)
return ans
复杂度
令 m, n 分别为数组 A 和数组 B 的长度。
使用数组表示哈希表统计,使用前缀和,后缀和计算最小操作次数
class Solution {
public:
int minCharacters(string a, string b) {
int res=INT_MAX;
//小写字母,用数组表示哈希表统计,足够
vector<int>countA(26,0);
vector<int>countB(26,0);
int sizeA=a.size();
int sizeB=b.size();
for(char ch:a){
countA[ch-'a']++;
}
for(char ch:b){
countB[ch-'a']++;
}
//利用前缀和,后缀和
int sumA=0,sumB=0;
for(int i=0;i<25;i++){
sumA+=countA[i];
sumB+=countB[i];
res=min(min(res,sizeA-countA[i]+sizeB-countB[i]),min(sizeA-sumA+sumB,sizeB-sumB+sumA));
}
res=min(res,sizeA-countA[25]+sizeB-countB[25]);
return res;
}
};
class Solution:
def minCharacters(self, A: str, B: str) -> int:
ca = collections.Counter(A)
cb = collections.Counter(B)
# ca 中严格大于 cb 的最小操作数
def greater_cost(ca, cb):
ans = float("inf")
# 枚举 ca 中的最小值
for i in range(1, 26):
count = 0
# 将 ca 中小于最小值的都进行一次操作
for j in range(i):
count += ca[chr(97 + j)]
# 将 cb 中大于等于最小值的都进行一次操作(注意这里的等号)
for j in range(i, 26):
count += cb[chr(97 + j)]
ans = min(ans, count)
return ans
def equal_cost(ca, cb):
ans = float("inf")
for i in range(26):
ans = min(ans, len(A) + len(B) - ca[chr(97 + i)] - cb[chr(97 + i)])
return ans
return min(greater_cost(ca, cb), greater_cost(cb, ca), equal_cost(ca, cb))
计数加模拟
var minCharacters = function(a, b) {
const n = a.length, m = b.length;
const va = new Array(26).fill(0);
const vb = new Array(26).fill(0);
let res = m + n;
for (let ch of a) {
va[ch.charCodeAt() - 'a'.charCodeAt()]++;
}
for (let ch of b) {
vb[ch.charCodeAt() - 'a'.charCodeAt()]++;
}
let res1 = m + n;
for (let i = 0; i < 25; i++) {
let cur = 0;
for (let j = i + 1; j < 26; j++) cur += va[j];
for (let j = 0; j <= i; j++) cur += vb[j];
res1 = Math.min(res1, cur);
}
res = Math.min(res, res1);
let res2 = m + n;
for (let i = 0; i < 25; i++) {
let cur = 0;
for (let j = i + 1; j < 26; j++) cur += vb[j];
for (let j = 0; j <= i; j++) cur += va[j];
res2 = Math.min(res2, cur);
}
res = Math.min(res, res2);
let res3 = m + n;
for (let i = 0; i < 26; i++) {
let cur = 0;
for (let j = 0; j < 26; j++) {
if (i == j) continue;
cur += va[j] + vb[j];
}
res3 = Math.min(res3, cur);
}
res = Math.min(res, res3);
return res;
};
26数组储存前缀和。遍历26个字母,依次验证三个条件:1. a最大为这个字母,b>a; 2. b最大为这个字母,a>b; 3. a,b全部为这个字母
class Solution {
public int minCharacters(String a, String b) {
int[] countA = new int[26];
int[] countB = new int[26];
for (char c : a.toCharArray()) {
countA[c - 'a']++;
}
for (char c : b.toCharArray()) {
countB[c - 'a']++;
}
for (int i = 1; i < 26; i++) {
countA[i] += countA[i - 1];
countB[i] += countB[i - 1];
}
int minOp = Integer.MAX_VALUE;
for (char c = 'a'; c <= 'z'; c++) {
minOp = Math.min(minOp,
Math.min(distinctLetter(c, countA, countB),
Math.min(aLessThanB(c, countA, countB), aLessThanB(c, countB, countA))
)
);
}
return minOp;
}
private int aLessThanB(char c, int[] countA, int[] countB) {
if (c == 'z') {
return Integer.MAX_VALUE;
}
int changeA = countA['z' - 'a'] - countA[c - 'a'];
int changeB = countB[c - 'a'];
return changeA + changeB;
}
private int distinctLetter(char c, int[] countA, int[] countB) {
int changeA = countA['z' - 'a'] - countA[c - 'a'] + (c == 'a' ? 0 : countA[c - 1 - 'a']);
int changeB = countB['z' - 'a'] - countB[c - 'a'] + (c == 'a' ? 0 : countB[c - 1 - 'a']);
return changeA + changeB;
}
}
time: O(m + n)
space: 26
统计每个字母出现的个数,然后分别统计三种方式
class Solution:
def minCharacters(self, a: str, b: str) -> int:
counter_a,counter_b = [0]*26, [0]*26
way_1,way_2,way_3 = [],[],[]
for c in a:
counter_a[ord(c)-ord('a')] += 1
for c in b :
counter_b[ord(c)-ord('a')] += 1
for i in range(1,26):
way_1.append(sum(counter_a[i:])+sum(counter_b[:i]))
for i in range(1,26):
way_2.append(sum(counter_b[i:])+sum(counter_a[:i]))
for i in range(26):
way_3.append(len(a)+len(b)-counter_a[i]-counter_b[i])
way_1 = min(way_1)
way_2 = min(way_2)
way_3 = min(way_3)
return min(way_1,way_2,way_3)
时间复杂度:O(m+n) 空间复杂度:O(26)
判断threshold
class Solution {
public int minCharacters(String a, String b) {
int aLength = a.length(), bLength = b.length();
int totalLength = aLength + bLength;
int[] count1 = new int[26], count2 = new int[26];
int res = totalLength; // res是num_of_swaps_needed
// Load-in frequency data
for (int i = 0; i < aLength; ++i)
count1[a.charAt(i) - 'a']++;
for (int i = 0; i < bLength; ++i)
count2[b.charAt(i) - 'a']++;
// Iterate thourgh all possible threshold
for (int i=0; i<26; i++) {
// Condition_3: a == b
res = Math.min(res, aLength + bLength - count1[i] - count2[i]);
// For culmulative frequency of String's Characters
if (i > 0) {
count1[i] += count1[i - 1];
count2[i] += count2[i - 1];
}
// Evaluating thresholds, find one with min swaps
if (i < 25) {
int threshold = i;
// Condition_2: b < a
// b中要置换掉比threshold大的char,a中要置换掉比threshold小的值
res = Math.min(res, (bLength - count2[threshold]) + count1[threshold]);
System.out.println(bLength - count2[threshold] + count1[threshold]);
// Condition_1: b > a
// b中要置换掉比threshold小的char,a中要置换掉比threshold大的值
res = Math.min(res, (aLength - count1[threshold]) + count2[threshold]);
}
}
return res;
}
}
from collections import Counter
class Solution:
def minCharacters(self, a: str, b: str) -> int:
def da(aa,bb):
countera = Counter(aa)
counterb = Counter(bb)
ansl = []
for i in range(25):
p = 0
xxx = chr(ord('a') + i)
for k,v in countera.items():
if k > xxx:
p += v
for k,v in counterb.items():
if k <= xxx:
p += v
ansl.append(p)
res1 = min(ansl)
return res1
res1 = da(a,b)
res2 = da(b,a)
countera = Counter(a)
counterb = Counter(b)
countersum = countera +counterb
dicsum = dict(countersum)
dicls = list(dicsum.values())
maxab = max(dicls)
res3 = len(a) + len(b) - maxab
res = min([res1,res2,res3])
print(res1,res2,res3)
return res
时间复杂度:O(N) 空间复杂度:O(N)
思路 每一个字符c(c取值从a..z)都有可能是字符串A和字符串B的“分割字符”。
public int minCharacters(String a, String b) {
int[] ac = new int[26];
int[] bc = new int[26];
for (char c : a.toCharArray()) {
ac[c - 'a']++;
}
for (char c : b.toCharArray()) {
bc[c - 'a']++;
}
//第三个条件,修改字符最少,改成同一个字符
int ans = a.length() + b.length();
for(int i=0; i<26; i++) {
ans = Math.min(ans, a.length() + b.length() - ac[i] - bc[i]);
}
return Math.min(ans, Math.min(smaller(ac, bc), smaller(bc, ac)));
}
private int smaller(int[] a, int[] b) {
//第一个第二个条件类似,封装到一个方法
//因为字母总共就26个,所以枚举所有可能, 依次判断a中所有元素小于等于字符k,b中所有元素大于字符k,然后求出最小值即可
int ans = Integer.MAX_VALUE;
for(int i=0; i < 25; i++) {//因为z是最大的元素,所以不能让a中所有元素小于等于z,这一点需要排除,所以只循环到24
int total = 0;//需要修改的元素的总数
for(int j=i+1; j<26; j++) {//把a中素有大于i的元素统计起来,保证a中所有元素小于等于i,需要遍历a中所有元素
total += a[j];
}
for(int j=0; j<=i; j++) {//把b中所有小于等于元素i的都统计起来,使调整后所有元素都大于i
total += b[j];
}
ans = Math.min(ans, total);
}
return ans;
}
时间复杂度:O(n) 空间复杂度:O(1)
直接模拟即可
def minCharacters(self, a: str, b: str) -> int:
counter_a = [0] * 26
counter_b = [0] * 26
for temp_a in a:
counter_a[ord(temp_a) - ord("a")] += 1
for temp_b in b:
counter_b[ord(temp_b) - ord("a")] += 1
ans = len(a) + len(b)
for i in range(26):
ans = min(ans, len(a) + len(b) - counter_a[i] - counter_b[i])
# a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母
for i in range(1, 26):
t = 0
for j in range(i, 26):
t += counter_a[j]
for j in range(i):
t += counter_b[j]
ans = min(ans, t)
# a 中的 每个字母 在字母表中 严格大于 b 中的 每个字母
for i in range(1, 26):
t = 0
for j in range(i, 26):
t += counter_b[j]
for j in range(i):
t += counter_a[j]
ans = min(ans, t)
return ans
时间 O(m) + O(n) \ 空间 O(26)
class Solution:
def minCharacters(self, a: str, b: str) -> int:
A = [0] * 26 # A和B分别存储字符串a和b中每个字母(26个)出现的次数
B = [0] * 26 # A=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for ch in a:
A[ord(ch)-ord('a')] += 1
for ch in b:
B[ord(ch)-ord('a')] += 1
n1, n2 = len(a), len(b)
presum1 = presum2 = 0
ans = n1+n2
for i in range(25):
presum1 += A[i]
presum2 += B[i]
ans = min(ans, n1-presum1+presum2)
ans = min(ans, presum1+n2-presum2)
ans = min(ans, n1-A[i] + n2-B[i])
ans = min(ans, n1-A[25] + n2-B[25])
return ans
时间复杂度:O(n+m+26)
空间复杂度:O(26)
Day35
1、枚举所有可能出现的结果,找出操作数最少的一种
2、第一种情况是将a字符中的字符都换成小于a[i]字母,同时将b字符中的字符都换成大于a[i]的字母
3、第二种情况是相反的
4、第三种情况是求两者的字符串长度,并减去a[i]字母在a,b中的个数
var minCharacters = function(a, b) {
let da = new Array(26).fill(0);
let db = new Array(26).fill(0);
//两个数组分别记录两个字符串中不同字母出现的次数
for(let i in a) {
da[a.charCodeAt(i) - 97] ++;
}
for(let i in b) {
db[b.charCodeAt(i) - 97] ++;
}
let an = a.length, bn = b.length, asum = 0, bsum = 0, res = Number.MAX_SAFE_INTEGER;
for(let i = 0 ; i < 25 ; i ++) {
asum += da[i];
bsum += db[i];
//asum的意思是求出a中<=第i个字母的个数
res = Math.min(res, an+bn-da[i]-db[i], an-asum+bsum, bn-bsum+asum);
//an+bn-da[i]-db[i]的意思是将a和b都换成同一个字母所需的操作数
//an-asum+bsum的意思是将a中都换成小于第i个字母,b中都换成大于第i个字母所需的操作数
}
return Math.min(res, an+bn-da[25]-db[25]);
//由于没有比z大的字符,故需要单独处理z字符
};
时间复杂度:O(n)
空间复杂度:O(1)
class Solution: def minCharacters(self, a: str, b: str) -> int: acnt, bcnt = [0] 26, [0] 26 for c in a: acnt[ord(c)-97] += 1 for c in b: bcnt[ord(c)-97] += 1
res = float('inf')
for thre in range(26):
if thre>0:
change = 0
for j in range(thre,26):
change += acnt[j]
for j in range(0,thre):
change += bcnt[j]
res = min(res,change)
change = 0
for j in range(thre,26):
change += bcnt[j]
for j in range(0,thre):
change += acnt[j]
res = min(res,change)
change = 0
for j in range(26):
if j!= thre:
change += acnt[j]
change += bcnt[j]
res = min(res,change)
return res
···js
/**
@param {string} a @param {string} b @return {number} / / @param {string} a @param {string} b @return {number} / var minCharacters = function(a, b) { let da = new Array(26).fill(0); let db = new Array(26).fill(0); for(let i in a) { da[a.charCodeAt(i) - 97] ++; } for(let i in b) { db[b.charCodeAt(i) - 97] ++; } let an = a.length, bn = b.length, asum = 0, bsum = 0, res = Number.MAX_SAFE_INTEGER; for(let i = 0 ; i < 25 ; i ++) { asum += da[i]; bsum += db[i]; res = Math.min(res, an+bn-da[i]-db[i], an-asum+bsum, bn-bsum+asum); } return Math.min(res, an+bn-da[25]-db[25]); };
https://leetcode-cn.com/problems/change-minimum-characters-to-satisfy-one-of-three-conditions/
并没有理解这个解题思路
class Solution {
/**
* @param String $a
* @param String $b
* @return Integer
*/
function minCharacters($a, $b) {
$fA = $fB = $fC = array_fill(0, 26, 0);
for ($i = 0; $i < strlen($a); ++$i)
$fA[ord($a[$i]) - 97]++; // $fA = [0=>2, 1=>1]
for ($i = 0; $i < strlen($b); ++$i)
$fB[ord($b[$i]) - 97]++; // $fB = [0=>2, 2=>1]
$c = $a . $b;
for ($i = 0; $i < strlen($c); ++$i)
$fC[ord($c[$i]) - 97]++; // $fC = [0=>4, 2=>1, 1=>1]
$ans = array_sum($fC) - max($fC); // 2
for ($i = 1; $i < 26; ++$i) {
$ans = min($ans, array_sum(array_slice($fA, 0, $i)) + array_sum(array_slice($fB, $i))); // 2
$ans = min($ans, array_sum(array_slice($fB, 0, $i)) + array_sum(array_slice($fA, $i))); // 2
}
return $ans;
}
}
时间复杂度:O(m+n),m和n表示字符a和b的长度 空间复杂度:O(26)
原来是用这种方式解决的吗,真是太厉害了(艾琳大拇指)
int minCharacters(string a, string b) {
vector<int> acnt(26,0);
vector<int> bcnt(26,0);
int an=a.size(),bn=b.size();
for(char c:a) acnt[c-'a']++;
for(char c:b) bcnt[c-'a']++;
int ans=INT_MAX;
int asum=0,bsum=0;
for(int i=0;i<25;i++){
asum+=acnt[i];
bsum+=bcnt[i];
ans=min(min(ans,an-acnt[i]+bn-bcnt[i]),min(an-asum+bsum,bn-bsum+asum));
}
ans=min(ans,an-acnt[25]+bn-bcnt[25]);
return ans;
}
class Solution {
public int minCharacters(String a, String b) {
// count letters in a and b
int[] acnt = new int[26];
int[] bcnt = new int[26];
int an = a.length(), bn = b.length();
for (char c: a.toCharArray()) {
acnt[c - 'a']++;
}
for (char c: b.toCharArray()) {
bcnt[c - 'a']++;
}
// traverse two cnt to calculate the minimum ops
int ans = Integer.MAX_VALUE, ans_1, ans_2, asum = 0, bsum = 0;
for (int i = 0; i < 25; i++) {
asum += acnt[i];
bsum += bcnt[i];
// # of operations to meet 1 or 2:
// make letters in 'a' less than i, letters in 'b' greater than i
ans_1 = Math.min(an - asum + bsum, bn - bsum + asum);
// # of operations to meet 3:
// turn all letters beside 'i' itself into 'i'
ans_2 = Math.min(ans, an - acnt[i] + bn - bcnt[i]);
ans = Math.min(ans_1, ans_2);
}
// the case of all 'z'
ans = Math.min(ans, an - acnt[25] + bn - bcnt[25]);
return ans;
}
}
注意特征,使用前缀和解决
var minCharacters = function(a, b) {
let da = new Array(26).fill(0);
let db = new Array(26).fill(0);
for(let i in a) {
da[a.charCodeAt(i) - 97] ++;
}
for(let i in b) {
db[b.charCodeAt(i) - 97] ++;
}
let an = a.length, bn = b.length, asum = 0, bsum = 0, res = Number.MAX_SAFE_INTEGER;
for(let i = 0 ; i < 25 ; i ++) {
// 前缀和计算
asum += da[i];
bsum += db[i];
// 找最小值
res = Math.min(res, an+bn-da[i]-db[i], an-asum+bsum, bn-bsum+asum);
}
// z的特殊处理
return Math.min(res, an+bn-da[25]-db[25]);
};
时间O(n) 空间O(1)
思路
代码
class Solution {
public:
int minCharacters(string a, string b) {
vector<int> a_num(26),b_num(26);
int a_length =a.size();
int b_length =b.size();
for(int i=0;i<a_length;i++){
a_num[a[i]-'a']++;
}
for(int j=0;j<b_length;j++){
b_num[b[j]-'a']++;
}
int max_ab_num=0; //字母最多的数量
for(int i=0;i<26;i++){
max_ab_num = max(max_ab_num,a_num[i]+b_num[i]);
}
// a 和 b 转换为相同字母需要的最小步数;
int min_step =0;
min_step= a_length+b_length-max_ab_num;
// a > b 或者 a < b
int sum_a=0;
int sum_b =0;
for(int i=0; i<25;i++){
sum_a += a_num[i];
sum_b += b_num[i];
// a 中的字符全部变为小于等于 a[i](i后边变), b 变为全部大于b[i](i前面部分变)
min_step = min(min_step, a_length-sum_a + sum_b);
// a 中的字符全部变为大于 a[i](i前面变), b 变为全部小于等于b[i](i后面部分变)
min_step = min(min_step, b_length-sum_b + sum_a);
}
return min_step;
}
};
复杂度分析 时间复杂度:O(m+n),m和n表示字符a和b的长度 空间复杂度:O(26*2)
找到一个基准字母,使得 a 中所有字母小于等于该基准值,且 b 中所有字母大于该基准值(或者相反)
三个条件对应三种情况,最终将模拟出的三种情况的最小值
class Solution {
public:
int minCharacters(string a, string b) {
int n = a.size(), m = b.size();
vector<int> va(26, 0), vb(26, 0);
for (char c : a) {
va[c - 'a']++;
}
for (char c : b) {
vb[c - 'a']++;
}
int ret = n + m;
// 第一种情况
int case1 = n + m;
for (int i = 0; i < 25; i++) {
// 以第 i 个字母为临界(字符a可取,b不可取)
int cur = 0;
for (int j = i + 1; j < 26; j++) {
cur += va[j];
}
for (int j = 0; j <= i; j++) {
cur += vb[j];
}
case1 = min(case1, cur);
}
ret = min(ret, case1);
// 第二种情况
int case2 = n + m;
for (int i = 0; i < 25; i++) {
// 以第 i 个字母为临界(字符b可取,a不可取)
int cur = 0;
for(int j = i + 1; j < 26; j++) {
cur += vb[j];
}
for (int j = 0; j <= i; j++) {
cur += va[j];
};
case2 = min(case2, cur);
}
ret = min(ret, case2);
// 第三种情况
int case3 = n + m;
for (int i = 0; i < 26; i++) {
int cur = 0;
for (int j = 0; j < 26; j++) {
if (j == i)
continue;
cur += va[j] + vb[j];
}
case3 = min(case3, cur);
}
ret = min(ret, case3);
return ret;
}
};
复杂度分析
满足三条件之一需要改变的最少字符数 https://leetcode-cn.com/problems/change-minimum-characters-to-satisfy-one-of-three-conditions/
维护两个数组,判断满足三个条件的最小次数
class Solution {
public:
int minCharacters(string a, string b) {
vector<int> va(26),vb(26);
for(char c:a){
va[c - 'a'] ++;
}
for(char c:b){
vb[c - 'a'] ++;
}
int t = 0;
for(int i =0;i<26;i++){
t = max(t,va[i] + vb[i]);
}
int sa = a.size(), sb = b.size();
int res = sa+sb-t;
for(int i =25,ta = 0,tb = 0; i>0;i--){
ta += va[i];
tb += vb[i];
res = min(res,min(ta+sb - tb, tb + sa -ta));
}
return res;
}
};
时间复杂度:O(M+N) 空间复杂度:O(N)
前缀和,计数数组
class Solution:
def minCharacters(self, a: str, b: str) -> int:
acnt = [0]*26
bcnt = [0]*26
a_size = len(a)
b_size = len(b)
for char in a:
acnt[ord(char)-ord('a')] += 1
for char in b:
bcnt[ord(char)-ord('a')] += 1
ans = max(a_size, b_size)
prefix_a = 0
prefix_b = 0
for i in range(25):
prefix_a += acnt[i]
prefix_b += bcnt[i]
ans = min(min(ans, a_size-acnt[i]+b_size-bcnt[i]), min(a_size-prefix_a+prefix_b, b_size-prefix_b+prefix_a))
ans = min(ans, a_size-acnt[25]+b_size-bcnt[25])
return ans
func minCharacters(a string, b string) int {
aCount := [26]int{}
bCount := [26]int{}
for _, val := range a {
aCount[val-'a']++
}
for _, val := range b {
bCount[val-'a']++
}
aSize := len(a)
bSize := len(b)
ans := max(aSize, bSize)
prefixSumA := 0
prefixSumB := 0
for i:=0; i<25;i++ {
prefixSumA += aCount[i]
prefixSumB += bCount[i]
// min(min(ans, a_size-acnt[i]+b_size-bcnt[i]), min(a_size-prefix_a+prefix_b, b_size-prefix_b+prefix_a))
ans = min(min(ans, aSize-aCount[i]+bSize-bCount[i]),min(aSize-prefixSumA+prefixSumB, bSize-prefixSumB+prefixSumA))
}
ans = min(ans, aSize-aCount[25]+bSize-bCount[25])
return ans
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
时间复杂度:O(M+N) 空间复杂度:O(1)
计数数组
class Solution {
public:
int minCharacters(string a, string b) {
vector<int> count_a(26,0);
vector<int> count_b(26,0);
for(char & c: a)
{
count_a[c - 'a'] +=1;//下标表示字符
}
for(char& c : b)
{
count_b[c - 'a'] +=1;
}
int sum = a.size() + b.size();
int option3 = equa_cost(count_a,count_b,sum);
int option1 = great_cost(count_b,count_a);
int option2 = great_cost(count_a,count_b);
return min({option1,option2,option3});
}
int great_cost(vector<int>& count_a, vector<int>& count_b)//a >b
{
int res = INT_MAX;
for(int i = 1; i<26;i++)//a取不到
{
int op = 0;
for(int j = i; j<26;j++)
{
op += count_b[j];
}
for(int j = 0; j<i; j++)
{
op += count_a[j];
}
res = min(res, op);
}
return res;
}
int equa_cost(vector<int>& count_a,vector<int>& count_b,int size)
{
int res = INT_MAX;
for(int i = 0; i<26;i++)
{
res = min(res, size-count_a[i] - count_b[i]);
}
return res;
}
};
-时间复杂度O(M+N)
class Solution {
public int minCharacters(String a, String b) {
int[] cntA = new int[26], cntB = new int[26];
int lenA = a.length(), lenB = b.length();
for (int i = 0; i < lenA; i++) {
cntA[a.charAt(i) - 'a']++;
}
for (int i = 0; i < lenB; i++) {
cntB[b.charAt(i) - 'a']++;
}
int ans1, ans2, ans = Integer.MAX_VALUE;
int sumA = 0, sumB = 0;
for (int i = 0; i < 25; i++) {
sumA += cntA[i];
sumB += cntB[i];
ans1 = Math.min(lenA - sumA + sumB, lenB - sumB + sumA);
ans2 = Math.min(ans, lenA - cntA[i] + lenB - cntB[i]);
ans = Math.min(ans1, ans2);
}
return Math.min(ans, lenA - cntA[25] + lenB - cntB[25]);
}
}
枚举+计数数组
class Solution:
def minCharacters(self, a: str, b: str) -> int:
counter1,counter2=[0]*26,[0]*26
for c in a: counter1[ord(c)-ord('a')]+=1
for c in b: counter2[ord(c)-ord('a')]+=1
way1=min(sum(counter1[i:])+sum(counter2[:i]) for i in range(1,26))
way2=min(sum(counter2[i:])+sum(counter1[:i]) for i in range(1,26))
way3=min(len(a)+len(b)-counter1[i]-counter2[i] for i in range(26))
return min(way1,way2,way3)
枚举。先将a,b存储数组中,数组中存储每个字符的个数,数组下标对应1-26个字符。
第一种情况:遍历26个字符,假设a中最大字符为当前字符i,满足条件需要a中最大字符小于b中最小字符;则a中所有大于i的字符都需要操作(改成小于等i),b中所有小于等于i的字符都需要操作(改成大于i)。第二种情况是一样的。
对于第三种情况,a,b所有字符相等,遍历26个字符,假设将所有字符设置成当前字符i,则操作数为a,b总长度减去当前已经是i的字符数
var minCharacters = function(a, b) {
let c1 = new Array(26).fill(0);
let c2 = new Array(26).fill(0);
for (let i = 0; i < a.length; i++) c1[a[i].charCodeAt(0) - 97] += 1;
for (let i = 0; i < b.length; i++) c2[b[i].charCodeAt(0) - 97] += 1;
let res = a.length + b.length;
// r1: 第一种情况,a中所有字符小于b中所有字符;r2: 第二种情况,b中所有字符小于a中所有字符
for (let i = 0; i < 25; i++) {
let r1 = 0, r2 = 0;
for (let j = i + 1; j < 26; j++) {
r1 += c1[j];
r2 += c2[j];
}
for (let x = i; x >= 0; x--) {
r1 += c2[x];
r2 += c1[x];
}
res = Math.min(res, r1, r2);
}
// 第三种情况,a,b所有字符相等
for (let i = 0; i < 26; i++) res = Math.min(res, a.length + b.length - c1[i] - c2[i]);
return res;
};
time: O(m+n) m,n分别为a,b的长度
space: O(26)
Python3 Code:
class Solution:
def minCharacters(self, A: str, B: str) -> int:
counter_A = [0] * 26
counter_B = [0] * 26
for a in A:
counter_A[ord(a) - ord('a')] += 1
for b in B:
counter_B[ord(b) - ord('a')] += 1
ans = len(A) + len(B)
for i in range(26):
ans = min(ans, len(A) + len(B) - counter_A[i] - counter_B[i])
for i in range(1, 26):
t = 0
for j in range(i, 26):
t += counter_A[j]
for j in range(i):
t += counter_B[j]
ans = min(ans, t)
for i in range(1, 26):
t = 0
for j in range(i, 26):
t += counter_B[j]
for j in range(i):
t += counter_A[j]
ans = min(ans, t)
return ans
复杂度分析
令 n 为数组长度。
class Solution:
def minCharacters(self, a: str, b: str) -> int:
counter_A = [0] * 26
counter_B = [0] * 26
for i in a:
counter_A[ord(i) - ord('a')] += 1
for i in b:
counter_B[ord(i) - ord('a')] += 1
way1=min(sum(counter_A[i:])+sum(counter_B[:i]) for i in range(1,26))
way2=min(sum(counter_B[i:])+sum(counter_A[:i]) for i in range(1,26))
way3=min(len(a)+len(b)-counter_A[i]-counter_B[i] for i in range(26))
return min(way1,way2,way3)
class Solution {
public int minCharacters(String a, String b) {
return Math.min(lower(a, b), same(a, b));
}
private int same(String a, String b) {
int[] aa = new int[26];
int[] bb = new int[26];
for (int i = 0; i < a.length(); i++) {
aa[a.charAt(i) - 'a']++;
}
for (int j = 0; j < b.length(); j++) {
bb[b.charAt(j) - 'a']++;
}
int res = a.length() + b.length();
for (int i = 0; i < 26; i++) {
res = Math.min(res, a.length() + b.length() - aa[i] - bb[i]);
}
return res;
}
private int lower(String a, String b) {
int[] aamin = new int[26];
int[] aamax = new int[26];
for (int i = 0; i < 26; i++) {
for (int j = 0; j < a.length(); j++) {
if (a.charAt(j) - 'a' <= i) {
aamin[i]++;
}
if (a.charAt(j) - 'a' > i) {
aamax[i]++;
}
}
}
int[] bbmin = new int[26];
int[] bbmax = new int[26];
for (int i = 0; i < 26; i++) {
for (int j = 0; j < b.length(); j++) {
if (b.charAt(j) - 'a' <= i) {
bbmin[i]++;
}
if (b.charAt(j) - 'a' > i) {
bbmax[i]++;
}
}
}
int res = a.length() + b.length();
// 此处只需遍历到25,这是周赛最后一个用例没通过的原因
for (int i = 0; i < 25; i++) {
res = Math.min(res, a.length() - aamin[i] + b.length() - bbmax[i]);
res = Math.min(res, a.length() - aamax[i] + b.length() - bbmin[i]);
}
return res;
}
}
class Solution(object):
def minCharacters(self, a, b):
"""
:type a: str
:type b: str
:rtype: int
"""
counter_a = Counter(ord(letter)-ord('a') for letter in a);
counter_b = Counter(ord(letter)-ord('a') for letter in b);
option_3 = len(a) - max(counter_a.values()) + len(b) - max(counter_b.values());
print(max(counter_a.values()),max(counter_b.values()))
option_1= option_2 = len(a) + len(b)
print(counter_a, counter_b)
for i in range(1,26):
counter_a[i] += counter_a[i-1];
counter_b[i] += counter_b[i-1];
print(i,counter_a[i], counter_b[i], len(a), len(b))
option_1 = min(option_1, len(a)-counter_a[i]+ counter_b[i]);
option_2 = min(option_2 , len(b)-counter_b[i] + counter_a[i]);
return min(option_1, option_2, option_3)
var minCharacters = function(a, b) {
let da = new Array(26).fill(0);
let db = new Array(26).fill(0);
for(let i in a) {
da[a.charCodeAt(i) - 97] ++;
}
for(let i in b) {
db[b.charCodeAt(i) - 97] ++;
}
let an = a.length, bn = b.length, asum = 0, bsum = 0, res = Number.MAX_SAFE_INTEGER;
for(let i = 0 ; i < 25 ; i ++) {
// 前缀和计算
asum += da[i];
bsum += db[i];
// 找最小值
res = Math.min(res, an+bn-da[i]-db[i], an-asum+bsum, bn-bsum+asum);
}
// z的特殊处理
return Math.min(res, an+bn-da[25]-db[25]);
};
var minCharacters = function(a, b) {
let da = new Array(26).fill(0);
let db = new Array(26).fill(0);
for(let i in a) {
da[a.charCodeAt(i) - 97] ++;
}
for(let i in b) {
db[b.charCodeAt(i) - 97] ++;
}
let an = a.length, bn = b.length, asum = 0, bsum = 0, res = Number.MAX_SAFE_INTEGER;
for(let i = 0 ; i < 25 ; i ++) {
asum += da[i];
bsum += db[i];
res = Math.min(res, an+bn-da[i]-db[i], an-asum+bsum, bn-bsum+asum);
}
return Math.min(res, an+bn-da[25]-db[25]);
};
class Solution {
public:
int minCharacters(string a, string b) {
int ans = 0;
vector<int> countA(26,0), countB(26,0);
for(auto it : a) countA[it - 'a']++;
for(auto it : b) countB[it - 'a']++;
int sumA = a.size();
int sumB = b.size();
ans = sumA+sumB;
for (int i=0;i<26;i++) ans = min(ans,sumA+sumB-countA[i]-countB[i]);
int tmp = 0;
for (int i=1;i<26;i++){
tmp = 0;
for (int j = i;j<26;j++) tmp += countA[j];
for (int j = 0;j<i;j++) tmp += countB[j];
ans = min(ans,tmp);
}
for (int i=1;i<26;i++){
tmp = 0;
for (int j = i;j<26;j++) tmp += countB[j];
for (int j = 0;j<i;j++) tmp += countA[j];
ans = min(ans,tmp);
}
return ans;
}
};
class Solution:
def minCharacters(self, a: str, b: str) -> int:
counta = [0]*26
countb = [0]*26
for c in a:
counta[ord(c)-ord('a')] += 1
for c in b:
countb[ord(c)-ord('a')] += 1
# 以i为界,a中在右边的字母全部变(移到左边,这样a的字母全在左边),b的左边全部变
cond1 = min([sum(counta[i:]) + sum(countb[:i]) for i in range(1,26)])
cond2 = min([sum(countb[i:]) + sum(counta[:i]) for i in range(1,26)])
# 全部变成第i个字母需要多少步
cond3 = min([len(a) - counta[i] + len(b) - countb[i] for i in range(26)])
return min(cond1, cond2, cond3)
模拟所有情况
var minCharacters = function(a, b) {
let countA = new Array(26).fill(0);
let countB = new Array(26).fill(0);
let res = Infinity;
//统计字符串中各个字母的数量
for(let index in a){
countA[a.charCodeAt(index) - 'a'.charCodeAt()] += 1;
}
for(let index in b){
countB[b.charCodeAt(index) - 'a'.charCodeAt()] += 1;
}
let sumA = 0;
let sumB = 0;
//如果以字母i为分界,要满足条件1,则要求a中的大于i的字母全都要替换,b中小于等于i的字母全都要替换;满足条件2同理
//如果a、b全都转换成字母i,即满足条件3,则非字母i的元素全被替换
for(let i = 0; i < 25; i++){
sumA += countA[i];
sumB += countB[i];
res = Math.min(res, a.length - sumA + sumB, b.length - sumB + sumA, (a.length - countA[i]) + (b.length - countB[i]));
}
//当i=25时,代表字母z,没有比z更大的字母。所以以z字母为界时,只能是满足条件3
res = Math.min(res, (a.length - countA[25]) + (b.length - countB[25]))
return res;
}
时间复杂度:O(n)
空间复杂度:O(1)
-
class Solution:
def minCharacters(self, a: str, b: str) -> int:
counter_A = [0] * 26
counter_B = [0] * 26
## 计算字符串中各字母出现的次数
for ch in a:
counter_A[ord(ch)-ord('a')] += 1
for ch in b:
counter_B[ord(ch)-ord('a')] += 1
ans = len(a) + len(b)
# 第一种条件 枚举a中最大的字母,遍历字母表,第i个作为最大的字母
for i in range(1,26):
times = 0
# a 中大于等于 i 的所有字符都需要进行一次操作
for j in range(i,26):
times += counter_A[j]
# b 中小于 i 的所有字符都需要进行一次操作
for j in range(i):
times += counter_B[j]
ans = min(ans,times)
# 第二种条件 枚举b中的最大字母
for i in range(1,26):
times = 0
for j in range(i,26):
times += counter_B[j]
for j in range(i):
times += counter_A[j]
ans = min(ans,times)
# 第三种条件 两个字符串相等的情况
for i in range(26):
ans = min(ans, len(a)+len(b)-(counter_A[i]+counter_B[i]))
return ans
- 时间复杂度: $O(n+m)$ , 分别是两个字符串的长度
- 空间复杂度 $O(26)$
1737. 满足三条件之一需改变的最少字符数
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/change-minimum-characters-to-satisfy-one-of-three-conditions/
前置知识
题目描述
操作的最终目标是满足下列三个条件 之一 :
a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母 。 b 中的 每个字母 在字母表中 严格小于 a 中的 每个字母 。 a 和 b 都 由 同一个 字母组成。 返回达成目标所需的 最少 操作数。
示例 1:
输入:a = "aba", b = "caa" 输出:2 解释:满足每个条件的最佳方案分别是: 1) 将 b 变为 "ccc",2 次操作,满足 a 中的每个字母都小于 b 中的每个字母; 2) 将 a 变为 "bbb" 并将 b 变为 "aaa",3 次操作,满足 b 中的每个字母都小于 a 中的每个字母; 3) 将 a 变为 "aaa" 并将 b 变为 "aaa",2 次操作,满足 a 和 b 由同一个字母组成。 最佳的方案只需要 2 次操作(满足条件 1 或者条件 3)。 示例 2:
输入:a = "dabadd", b = "cda" 输出:3 解释:满足条件 1 的最佳方案是将 b 变为 "eee" 。
提示:
1 <= a.length, b.length <= 105 a 和 b 只由小写字母组成