• Leetcode第 368 场周赛


    元素和最小的山形三元组 II

    预处理前缀和后缀最小值,记为pre[i]和sa[i]
    对于当前编号i,如果前面的最小值和后面的最大值都小于nums[i],则记录ans[i] = nums[i]+pre[i-1]+sa[i+1]
    结果输出最小的ans[i]即可。

    合法分组的最少组数

    统计每一个数字出现的次数。将每一个数字分为大小为 d d d d + 1 d+1 d+1的组,令 d d d尽可能大。
    d d d不满足单调性,不好二分。思路时直接暴力。
    计最小出现次数为 m n mn mn,出现过的数字个数为 c n t cnt cnt,显然有 m n ∗ c n t ≤ n u m s . l e n g t h mn*cnt \le nums.length mncntnums.length
    而显然有 d + 1 ≤ m n d+1 \le mn d+1mn,因此直接枚举d
    对于某个数字i,其出现次数为 t o t i tot_i toti,若 d d d成立则需要满足存在x令 x d ≤ t o t i ≤ x ( d + 1 ) xd \le tot_i \le x(d+1) xdtotix(d+1)
    x = t o t i / d x = tot_i/d x=toti/d,即以 d d d为标准将 t o t i tot_i toti分为x组,此时还剩 t o t i % d tot_i\%d toti%d个元素,每一组中最多可以容纳 d + 1 d+1 d+1个元素,最多可以容纳x个元素,使x组的个数都变为%d+1%。因此只要满足 t o t i % d ≤ x tot_i\%d \le x toti%dx t o t i % d ≤ t o t i / d tot_i\%d \le tot_i/d toti%dtoti/d,则对数字 i i i而言 d d d是合法的分组。
    已知d,数字i的分组个数为 t o t i + d m n + 1 \frac{tot_i+d}{mn+1} mn+1toti+d x x x需要取最小值满足 x d ≤ t o t i ≤ x ( d + 1 ) xd \le tot_i \le x(d+1) xdtotix(d+1),有 ⌈ t o t i / ( d + 1 ) ⌉ ≤ x \lceil tot_i/(d+1)\rceil \le x toti/(d+1)⌉x,因此取 x = ⌈ t o t i d + 1 ⌉ x =\lceil \frac{tot_i}{d+1}\rceil x=d+1toti
    枚举 d d d,计算分组个数,求分组最小值即可,复杂度为 O ( m n ∗ c n t ) O(mn*cnt) O(mncnt)

    得到 K 个半回文串的最少修改次数

    数据只有200,想法是纯暴力
    M i n T i m e s [ i ] [ j ] MinTimes[i][j] MinTimes[i][j]为子串 s t r i j str_{ij} strij变成半回文串最少的次数,暴力计算,复杂度为 O ( n 4 ) O(n^4) O(n4)
    令dp[i][j]为以 s t r i str_i stri为结尾时分为 j j j段最少的操作次数
    d p [ i ] [ j ] = min ⁡ d p [ z ] [ j − 1 ] + M i n T i m e s [ z + 1 ] [ i ] dp[i][j] = \min dp[z][j-1]+MinTimes[z+1][i] dp[i][j]=mindp[z][j1]+MinTimes[z+1][i]
    总复杂度 O ( n 4 ) O(n^4) O(n4)
    计算MinTimes时可以将一个n优化成 n \sqrt n n 甚至预处理成 lg ⁡ n \lg n lgn,但是 O ( n 4 ) O(n^4) O(n4)也能过就是了,大概是数据比较弱吧

    class Solution {
    public:
        int MinTimes[210][210];
        int dp[210][210];
        int calTimes(string &s,int l,int r)
        {
            int ret = (1<<30);
            int len = r-l+1;
            while(--len)
            {
                if((r-l+1)%len)
                    continue;
                int ans = 0;
                for(int i=0;i<len;++i)
                {
                    string t1;
                    for(int j=l+i;j<=r;j+=len)
                        t1 += s[j];
                    for(int c=0;c<t1.size()/2;++c)
                        if(t1[c]!=t1[t1.size()-1-c])
                            ans++;
                }
                ret = min(ret,ans);
            }
            return ret;
        }
        int minimumChanges(string s, int k) {
            memset(dp,0x3f,sizeof(dp));
            dp[0][0] = 0;
            int l = s.size();     
            for(int i=0;i<l;++i)
            {
                for(int j=i+1;j<l;++j)
                {
                    MinTimes[i][j] = calTimes(s,i,j);
                }
                MinTimes[i][i] = (1<<30);
            }
            for(int i=0;i<l;++i)
            {
                for(int j=0;j<=i;++j)
                {
                    for(int z=1;z<=k;++z)
                    {
                        dp[i+1][z] = min(dp[i+1][z],dp[j][z-1]+MinTimes[j][i]);
                    }
                }
            }
            return dp[l][k];
        }
    };
    
    • 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
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    分块(一)
    【C++】进阶模板
    周四见 | 物流人的一周资讯
    基于JavaWeb+SpringBoot+Vue健身俱乐部系统的设计和实现
    ES6中的class对象和它的家人们
    对齐PyTorch,一文详解OneFlow的DataLoader实现
    同是负值像素,为何在matplotlib和opencv上显示不一样?
    JavaSE ---01 数据类型与运算符
    IPKISS Tutorials 2------导入IPKISS模块
    Python 学习之路: 常用断言汇总
  • 原文地址:https://blog.csdn.net/Yuzzzzzz/article/details/133984506