leetcode-pp / 91alg-7-daily-check

6 stars 0 forks source link

【Day 35 】2022-05-05 - 1737. 满足三条件之一需改变的最少字符数 #38

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

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 只由小写字母组成

HuiWang1020 commented 2 years ago

Idea

Count and simulation.
step1: count frequency of letter in a and b.
step2: Enumerate every condition and find the min.

  1. Enumerate a-z to meet the condition .

    1. 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

      Code

      
      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)
JiangWenqi commented 2 years ago

题目没看太懂。。。

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)

maybetoffee commented 2 years ago
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;
    }
}
PFyyh commented 2 years ago
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;
    }
}
BlueRui commented 2 years ago

Problem 1737. Change Minimum Characters to Satisfy One of Three Conditions

Algorithm

Complexity

Code

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;
}
ShawYuan97 commented 2 years ago

思路

  1. 枚举出两个字符串中,大于某字母的个数以及小于某字母的个数,这两个个数相加就是保证字符串大于另一个字符串的修改次数
  2. 对于使两个字符串相同,那么只需要合并两个字符串,总的字符串长度减去出现最多字符次数

    关键点

代码

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长度。

L-SUI commented 2 years ago

···js

/**

houmk1212 commented 2 years ago

思路

看了题解,才有的思路。将问题转化成找到一个基准字母,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;
    }
}

复杂度

lxgang65 commented 2 years ago
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;
    }
}
TonyLee017 commented 2 years ago

思路

hyh331 commented 2 years ago

Day35 思路

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;

    }
};

复杂度分析

zhulin1110 commented 2 years ago

题目地址(1737. 满足三条件之一需改变的最少字符数)记录一下

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]);
};

复杂度分析

wychmod commented 2 years ago

思路

先转化为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

Magua-hub commented 2 years ago

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;
    }
};
Geek-LX commented 2 years ago

5.5

思路

代码

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 的长度。

caterpillar-0 commented 2 years ago

思路

使用数组表示哈希表统计,使用前缀和,后缀和计算最小操作次数

代码

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;
    }
};

复杂度分析:

currybeefer commented 2 years ago
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))
MoonLee001 commented 2 years ago

思路

计数加模拟

代码

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;
};

复杂度分析

LyuliangLiu commented 2 years ago

Idea

26数组储存前缀和。遍历26个字母,依次验证三个条件:1. a最大为这个字母,b>a; 2. b最大为这个字母,a>b; 3. a,b全部为这个字母

Code

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;
    }
}

Complexity

time: O(m + n)

space: 26

biscuit279 commented 2 years ago

思路

统计每个字母出现的个数,然后分别统计三种方式

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)

MichaelXi3 commented 2 years ago

Idea

1973719588 commented 2 years ago
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)

lizimu0709 commented 2 years ago

思路 每一个字符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)

xingchen77 commented 2 years ago

思路

直接模拟即可

代码

    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)

oneline-wsq commented 2 years ago

代码

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)

KWDFW commented 2 years ago

Day35

1737、满足三条件之一需改变的最少字符数

javascript #枚举

思路

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)

Ellie-Wu05 commented 2 years ago

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
gfrxf commented 2 years ago

···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]); };

577961141 commented 2 years ago

1737. 满足三条件之一需改变的最少字符数

时间

题目链接

https://leetcode-cn.com/problems/change-minimum-characters-to-satisfy-one-of-three-conditions/

题目思路

并没有理解这个解题思路

题目的题解code

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)

zhishinaigai commented 2 years ago

原来是用这种方式解决的吗,真是太厉害了(艾琳大拇指)

代码

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;
    }
rzhao010 commented 2 years ago
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;
    }
}
tensorstart commented 2 years ago

思路

注意特征,使用前缀和解决

代码

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)

Quieter2018 commented 2 years ago

思路

  1. a 和 b 转换为相同字母需要的最小步数,找出同样字符数量最多的;
  2. a 中的字符全部变为小于等于 a[i](i后边变), b 变为全部大于b[i](i前面部分变)
  3. a 中的字符全部变为大于 a[i](i前面变), b 变为全部小于等于b[i](i后面部分变)

代码

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)

houyanlu commented 2 years ago

思路

找到一个基准字母,使得 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;
    }
};

复杂度分析

xiayuhui231 commented 2 years ago

题目

满足三条件之一需要改变的最少字符数 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)

LQyt2012 commented 2 years ago

思路

前缀和,计数数组

代码

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)

liuguang520-lab commented 2 years ago

思路

计数数组

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)

revisegoal commented 2 years ago

哈希表 + 前缀和

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]);
    }
}
weihaoxie commented 2 years ago

思路

枚举+计数数组

代码

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)

复杂度

miss1 commented 2 years ago

思路

枚举。先将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)

ShuqianYang commented 2 years ago

代码

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 为数组长度。

bzlff commented 2 years ago
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)
freedom0123 commented 2 years ago
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;
    }
}
xil324 commented 2 years ago
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)
xqy97 commented 2 years ago
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]);
};
AConcert commented 2 years ago
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]);
};
mo660 commented 2 years ago
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;
    }
};
linjunhe commented 2 years ago

思路

  1. 用两个数组记录每个字母出现的次数
  2. 枚举每一种情况,取最小

Code

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)

复杂度分析

XXjo commented 2 years ago

思路

模拟所有情况

代码

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)

flyzenr commented 2 years ago