• 【LeetCode】1898. 可移除字符的最大数目


    题目

    给你两个字符串 s 和 p ,其中 p 是 s 的一个 子序列 。同时,给你一个元素 互不相同 且下标 从 0 开始 计数的整数数组 removable ,该数组是 s 中下标的一个子集(s 的下标也 从 0 开始 计数)。
    请你找出一个整数 k(0 <= k <= removable.length),选出 removable 中的 前 k 个下标,然后从 s 中移除这些下标对应的 k 个字符。整数 k 需满足:在执行完上述步骤后, p 仍然是 s 的一个 子序列 。更正式的解释是,对于每个 0 <= i < k ,先标记出位于 s[removable[i]] 的字符,接着移除所有标记过的字符,然后检查 p 是否仍然是 s 的一个子序列。
    返回你可以找出的 最大 k ,满足在移除字符后 p 仍然是 s 的一个子序列。
    字符串的一个 子序列 是一个由原字符串生成的新字符串,生成过程中可能会移除原字符串中的一些字符(也可能不移除)但不改变剩余字符之间的相对顺序。

    示例 1:

    输入:s = “abcacb”, p = “ab”, removable = [3,1,0]
    输出:2
    解释:在移除下标 3 和 1 对应的字符后,“abcacb” 变成 “accb” 。
    “ab” 是 “accb” 的一个子序列。
    如果移除下标 3、1 和 0 对应的字符后,“abcacb” 变成 “ccb” ,那么 “ab” 就不再是 s 的一个子序列。
    因此,最大的 k 是 2 。

    示例 2:

    输入:s = “abcbddddd”, p = “abcd”, removable = [3,2,1,4,5,6]
    输出:1
    解释:在移除下标 3 对应的字符后,“abcbddddd” 变成 “abcddddd” 。
    “abcd” 是 “abcddddd” 的一个子序列。

    示例 3:

    输入:s = “abcab”, p = “abc”, removable = [0,1,2,3,4]
    输出:0
    解释:如果移除数组 removable 的第一个下标,“abc” 就不再是 s 的一个子序列。

    提示:

    1 <= p.length <= s.length <= 105
    0 <= removable.length < s.length
    0 <= removable[i] < s.length
    p 是 s 的一个 子字符串
    s 和 p 都由小写英文字母组成
    removable 中的元素 互不相同

    题解

    二分法
    左右边界值为0和数组长度
    不断改变左右边界值得到mid,移除mid个字符并比较

    class Solution {
    public:
        bool fun(string s,string p,vector<int>& nums,int mid)
        {
            for(int i=0;i<mid;i++)
            {
                s[nums[i]] = '&';//不能删除,删除就改变其他字符下标
            }
            int j=0;
            cout<<s<<endl;
            for(int i=0;i<s.length();i++)//这里不是字符串匹配而是元素匹配关系
            {
                if(s[i]==p[j])
                    j++;
                if(j==p.length())
                    return true;
            }
            return false;
        }
        int maximumRemovals(string s, string p, vector<int>& removable) {
            int left = 0;
            int right = removable.size();
            int res = 0;
            while(left<=right)
            {
                int mid = left + ((right-left)>>1);
    
                cout<<left<<"=="<<mid<<"=="<<right<<"==>";
    
                if(fun(s,p,removable,mid))
                {
                    left = mid+1;
                    res = mid;
                }
                else
                {
                    right = mid-1;
                }
            }
            return res;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    搞懂三极管
    磁盘格式化指南:如何正确对磁盘进行分区和初始化?
    Kafka - 15 Kafka Offset | 自动和手动提交Offset | 指定Offset消费 | 漏消费和重复消费 | 消息积压
    EureKa服务注册与发现(集群部署Eureka与支付模块集群部署、订单模块访问负载均衡调用支付服务实现)
    SpringBoot-生成验证码
    Python在股票交易中的应用
    JDBC详解
    CSDN 网络技能树学习打卡第1天
    集合原理简记
    如何从 apt-get 升级中排除特定软件包
  • 原文地址:https://blog.csdn.net/qq_45972928/article/details/126241528