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

这是一道我觉得很不错的题目,值得学习的深究

考点:字符串,动态规划,枚举法

题目:

给你一个字符串 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

解释:唯一的最优解是删除最前面两个字符。

题目解读:

字符串想要最终得到一串前面全是a,后面全是b

法一:

枚举法

  1. 遍历数组,先找a的个数,这会是答案的一种可能,因为大不了就把a全部删掉

  1. 从i=0开始遍历数组,我们假设从小于等于i的数全是a,i一直往后,一共就是这些可能的情况,所有的情况中最小值就是最优解

  1. 因为第一步已经求出来a的总数,所以随着i的变化不同情况对a的“看法”也是不一样的,也就是归属于左边的话那就是合理的,最后的总count可以--,同时,i的左边也会包含很多b,这些b也要删掉

class Solution {
public:
    int minimumDeletions(string s) {
        int counta=0;
        int countb=0;
        int count=0;
        for(auto l:s)
        {
          if(l=='a')//统计a的总数
          counta++;
        }
        count=counta;//count的一种情况
        for(int i=0;i<s.size();i++)
        {
            //开始对i所到之处逐个排查
                if(s[i]=='b')
                countb++;
                if(s[i]=='a')
                counta--;     
            count=min(count,(counta+countb));
        }
        return count;
    }
};

法二:

动态规划法

动归的思想:

  1. 状态定义 f[i]看作第i个元素之前的字符串需要调整好的至少调整次数

  1. 如果第i个字符是b那么此次f[i]和f[i-1]是一样的,因为前面已经调整好了,i的位置是b完全符合条件

  1. 如果第i个字符是a则需要分类讨论

1.把i前面的b全部消失的调整次数就是一种f[i]

2.如果i位置的a消失也就没有需要调整的烦恼了,a就只能牺牲掉自己,那么f[i]=f[i-1]+1(1就是把a删掉)

  1. 由此列出如果s[i]=='a'的状态方程 f[i]=(min(f[i-1]+1),countb)

  1. 因此如果遍历到b并不是什么都不需要做,还要记录下b的总数

class Solution {
public:
    int minimumDeletions(string s) {
        int countb=0;
        int f=0;
        for(auto& l:s)
        {
            if(l=='b')
            countb++;
            else
            f=min(f+1,countb);
        }//每次遍历都是求出当前字符以及之前的所有字符让其满足条件的最少调整次数,当遍历完,就可以得到最后一个字符之前的也就是整个字符串所需要的最少调整次数
        return f;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值