LC-1653. 使字符串平衡的最少删除次(前后缀分解、动态规划)

1653. 使字符串平衡的最少删除次数

难度中等54

给你一个字符串 s ,它仅包含字符 'a''b'

你可以删除 s 中任意数目的字符,使得 s 平衡 。当不存在下标对 (i,j) 满足 i < j ,且 s[i] = 'b' 的同时 s[j]= 'a' ,此时认为 s平衡 的。

请你返回使 s 平衡最少 删除次数。

示例 1:

输入:s = "aababbab"
输出:2
解释:你可以选择以下任意一种方案:
下标从 0 开始,删除第 2 和第 6 个字符("aababbab" -> "aaabbb"),
下标从 0 开始,删除第 3 和第 6 个字符("aababbab" -> "aabbbb")。

示例 2:

输入:s = "bbaaaaabb"
输出:2
解释:唯一的最优解是删除最前面两个字符。

提示:

  • 1 <= s.length <= 105
  • s[i] 要么是 'a' 要么是 'b'

前后缀分解

题解:0x3f https://leetcode.cn/problems/minimum-deletions-to-make-string-balanced/solution/qian-hou-zhui-fen-jie-yi-zhang-tu-miao-d-dor2/

class Solution {
    public int minimumDeletions(String s) {
        // 要删除的b都在前缀中
        // 要删除的a都在后缀中
        // 枚举分割点
        int del = 0;
        char[] arr = s.toCharArray();
        for(char c : arr){
            del += 'b' - c; // 统计 ‘a’ 的个数
        }
        int ans = del;
        for(char c : arr){
            // 'a' -> -1    'b' -> 1
            del += (c-'a')*2 - 1;
            ans = Math.min(ans, del);
        }
        return ans;
    }
}

动态规划:考虑每一位a是否保留

class Solution {
    // 平衡字符串要求每一个a之前不能有b(或每一个b之后不能有a),考虑每一位a(或b)是否保留;
    // 对于字符串s[0~i],如果保留最后一位a,那么就将它之前的b全部删掉,删除次数d[i]=这个a之前b的个数;
    // 若不保留,则删掉这个a后同时也要让s[0~i-1]平衡的删除次数最小,删除次数就是1+d[i-1];取两者较小值即可;
    // 即d[i]=min{cnt[i], 1 + d[i-1]},cnt[i]为当前遇到的最后一个a之前b的个数,d[i]可仅由i和i-1递推,因此可以只用一个变量维护d[i];
    public int minimumDeletions(String s) {
        int n = s.length();
        int res = 0; // dp
        int cnt = 0; // 统计a之前b的个数
        for(char c : s.toCharArray()){
            if(c == 'b') cnt++;
            else res = Math.min(cnt, 1 + res);
        }
        return res;
    }
}

你可能感兴趣的:(算法刷题记录,动态规划,leetcode,算法)