LeetCode---380周赛

这篇具有很好参考价值的文章主要介绍了LeetCode---380周赛。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目列表

3005. 最大频率元素计数

3006. 找出数组中的美丽下标 I

3007. 价值和小于等于 K 的最大数字

3008. 找出数组中的美丽下标 II

一、最大频率元素计数

LeetCode---380周赛,leetcode,算法,职场和发展

这题就是个简单的计数题,正常遍历统计数据即可,关键是你要会写代码逻辑。

代码如下(如果代码看不懂的,建议按照代码逻辑手动模拟几次)

//两次遍历
class Solution {
public:
    int maxFrequencyElements(vector<int>& nums) {
        unordered_map<int,int>mp;
        for(auto&e:nums) mp[e]++;
        int sum=0,mx=0;
        for(auto it=mp.begin();it!=mp.end();++it){
            if(mx<it->second){
                sum=it->second;
                mx=it->second;
            }else if(mx==it->second){
                sum+=mx;
            }
        }
        return sum;
    }
};

//一次遍历
class Solution {
public:
    int maxFrequencyElements(vector<int>& nums) {
        int mx=0,s=0;
        unordered_map<int,int>cnt;
        for(auto x:nums){
            cnt[x]++;
            if(cnt[x]>mx){
                s=mx=cnt[x];
            }else if(cnt[x]==mx){
                s+=mx;
            }
        }
        return s;
    }
};

二、找出数组中的美丽下标I&II

LeetCode---380周赛,leetcode,算法,职场和发展

这题就按照题目说的去模拟就行,关键是优化时间复杂度,当然这题暴力也可以过,但是第四题就不行了。这里先用暴力去写。

简单说一下思路:先分别找出字符串a、b在s中可以匹配的位置,放到两个数组中,然后再找出符合条件的字符串a的下标,最后返回答案即可

代码如下

class Solution {
    vector<int> Get(string& s,string& a){
        vector<int>v;
        size_t pos=s.find(a);
        while(pos!=string::npos){
            v.push_back(pos);
            pos=s.find(a,pos+1);
        }
        return v;
    }
public:
    vector<int> beautifulIndices(string s, string a, string b, int k) {
        int n=s.size();
        vector<int>va=Get(s,a);
        vector<int>vb=Get(s,b);
        vector<int>ans;
        for(int i=0;i<va.size();i++){
            for(int j=0;j<vb.size();j++){
                if(abs(va[i]-vb[j])<=k){
                    ans.push_back(va[i]);
                    break;
                }
            }
        }
        return ans;
    }
};

如何优化时间复杂度?

在上面的代码中,代码的逻辑有两个模块:1、字符串匹配    2、找符合条件的下标

针对上面的两个模块,我们的优化方案如下

1、对字符串匹配的优化---KMP算法---这个后面会出文章具体讲该算法的原理,这里就不细说了

2、找符合条件的下标,我们的暴力写法没有用到两个数组有序的条件,一般来说,数组有序都可以有优化的方法,这里就可以用双指针,操作和原理如下

设 i 和 j 为va、vb数组的下标

1、va[ i ] < vb[ j ]

  • vb[ j ] - va[ i ] <= k 满足条件,将va[i]加入答案,i++,j不用加,因为vb[ j ]有可能让va[i+1]也符合条件
  • vb[ j ] - va[ i ] > k 不满足条件,i++,因为vb[j]后面的数只会离va[i]最来越远,i不可能在满足条件,j不用加,因为vb[ j ]有可能让va[i+1]也符合条件

2、va[ i ] >= vb[ j ]

  • va[ i ] - vb[ j ] <= k 满足条件,将va[i]加入答案,i++,j不用加,因为vb[ j ]有可能让va[i+1]也符合条件
  • va[ i ] - vb[ j ] > k 不满足条件,j++,i不变,因为vb[ j + 1] 可能离va[ i ]更近

双指针的本质就是让va[ i ]尽可能地与它相隔最近的vb[ j ]比较,从而避免一些没有必要的比较,在上面的遍历过程中只有i++和j++,时间复杂度为O(m+n)(m、n为两个数组的大小)

当然用二分查找也能优化,但是双指针更快。

代码如下(双指针+KMP)

class Solution {
    //KMP
    vector<int> Get(string& s,string& a){
        int n=a.size();
        vector<int>next(n);
        for(int i=1,j=0;i<n;i++){
            while(j&&a[j]!=a[i])
                j=next[j-1];
            if(a[j]==a[i])
                j++;
            next[i]=j;
        }

        vector<int>ret;
        for(int i=0,j=0;i<s.size();i++){
            while(j&&s[i]!=a[j])
                j=next[j-1];
            if(s[i]==a[j])
                j++;
            if(j==n){
                ret.push_back(i-n+1);
                j=next[j-1];
            }
        }
        return ret;
    }
public:
    vector<int> beautifulIndices(string s, string a, string b, int k) {
        vector<int>va=Get(s,a);
        vector<int>vb=Get(s,b);
        vector<int>ans;
        int n=va.size(),m=vb.size();
        int i=0,j=0;
        while(i<n&&j<m){
            if(va[i]<vb[j]){
                if(vb[j]-va[i]<=k)
                    ans.push_back(va[i]);
                i++;
            }else{
                if(va[i]-vb[j]<=k){
                    ans.push_back(va[i]);
                    i++;
                }else{
                    j++;
                }
            }
        }
        return ans;
    }
};

三、价值和小于等于K的最大数字

LeetCode---380周赛,leetcode,算法,职场和发展

题目中出现小于等于求最大,一般是用二分 (对二分不了解的可以看看我之前写的二分查找详解),下面我们来分析一下,是否能用二分来做?即是否具有单调性。我们知道 num 越大,整数的价值和就会越大, 两者成正比,满足单调性,那么就能用二分来做。

(二分的上下界选择问题:一般我们选0为下界,选一个极大值作为上界,让答案在区间内即可,如果你想要更为精确的上下界,这里也简单说明一下,0为下界没什么好说的,那么这个上界怎么得到呢?这题可以这么想,我们只求每个整数第x位上的1,需要的数字为多少?[ 低于x的位不考虑 因为我们取的是一个区间,并不要求准确 ] 是 k<<x <=> k*2^x )

现在关键在于如何判断 [1,num] 区间内的整数价值和是否满足条件,即如何求该区间的价值和?

这里有两种做法:1、数位dp(暴力)     2、找数学规律

数位dp上周才写过,套路都差不多,这里就不多介绍了,代码如下

class Solution {
    typedef long long LL;
public:
    LL check(LL n,int x){
        //下面写的数位dp是从高位到低位枚举二进制
        //当然你也可以将n处理得到它的二进制字符串,都是可以的
        int m=64-__builtin_clz(n);
        vector<vector<LL>>memo(m,vector<LL>(m+1,-1));
        function<LL(int,int,bool)>dfs=[&](int i,int j,bool limit_high)->LL{
            if(i<0)
                return j;
            if(!limit_high&&memo[i][j]!=-1) return memo[i][j];
            LL res=0;
            int up=limit_high?(n>>i)&1:1;
            for(int d=0;d<=up;d++)
                res+=dfs(i-1,j+(d==1&&(i+1)%x==0),limit_high&&up==d);
            if(!limit_high)
                memo[i][j]=res;
            return res;
        };
        return dfs(m-1,0,true);
    }
    long long findMaximumNumber(long long k, int x) {
        LL l=0,r=k<<x;
        while(l<=r){
            LL mid=l+(r-l)/2;
            if(check(mid,x)<=k)//二分的判断条件 
                l=mid+1;
            else 
                r=mid-1;
        }
        return r;
    }
};

下面来讲讲数学规律

题目要求特定二进制位上的1的个数,那么我们是不是可以看看这些特定二进制位对1的贡献,然后将贡献相加得到1的个数,解析如下

LeetCode---380周赛,leetcode,算法,职场和发展文章来源地址https://www.toymoban.com/news/detail-824063.html

class Solution {
    typedef long long LL;
public:
    LL check(LL n,int x){
        LL ans=0;
        int i=x-1;
        for(LL y = n>>i; y; y>>=x,i+=x){
            ans+=(y/2)<<i;//求[1,(n>>i)-1]的奇数个数
            if(y%2){
                // LL mask=(1LL<<i)-1;
                // ans+=(n&mask)+1;//注意这里是n
                LL mod=1LL<<i;
                ans+=n%mod+1;//注意这里是n
            }
        }
        return ans;
    }

    long long findMaximumNumber(long long k, int x) {
        LL l=0,r=k<<x;
        while(l<=r){
            LL mid=l+(r-l)/2;
            if(check(mid,x)<=k) l=mid+1;
            else r=mid-1;
        }
        return r;
    }
};

到了这里,关于LeetCode---380周赛的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode周赛】LeetCode第370场周赛

    一场比赛中共有 n 支队伍,按从 0 到 n - 1 编号。 给你一个下标从 0 开始、大小为 n * n 的二维布尔矩阵 grid 。对于满足 0 = i, j = n - 1 且 i != j 的所有 i, j :如果 grid[i][j] == 1,那么 i 队比 j 队 强 ;否则,j 队比 i 队 强 。 在这场比赛中,如果不存在某支强于 a 队的队伍,则认为

    2024年02月05日
    浏览(48)
  • Leetcode array 704 27 189 121 380 238 134 13

    二分搜索: 判断条件是left 和 right 这里就要注意区间开闭的问题 因为需要运行时间时O(1),所以要加上map 删除的时候要把需要删除的变到最后,再直接pop掉 rand用法: 1.rand() 2. nums[rand() % nums.size()]; 3. left+rand() % (right-left)

    2024年02月09日
    浏览(34)
  • [LeetCode108双周赛&LeetCode353周赛] 学习用记忆化搜索解决 DP 问题

    参考灵神直播和代码 @cache 装饰器的作用:将传入不同参数得到的函数值存储到缓存,避免下次传递相同参数重复计算结果,可用于解决递归函数重复计算问题,比如递归求斐波那契问题。 https://leetcode.cn/problems/maximum-number-of-jumps-to-reach-the-last-index/ 记忆化搜索 dfs(i) 表示以

    2024年02月13日
    浏览(36)
  • [LeetCode周赛复盘] 第 353 场周赛20230709

    感觉有奖品大家都来了。 T1 数学。 T2 dp。 T3 dp。 T4 差分/BIT RUPQ。 6451. 找出最大的可达成数字 1. 题目描述 2. 思路分析 为了使x num在t步内相同,需要相向而行,每步最大缩短距离是2,那么t步距离是2t。 3. 代码实现 6899. 达到末尾下标所需的最大跳跃次数 1. 题目描述 2. 思路分

    2024年02月15日
    浏览(32)
  • [LeetCode周赛复盘] 第 359 场周赛20230820

    T1 模拟。 T2 数学贪心。 T3 dp。 T4 分组+滑窗。 2828. 判别首字母缩略词 1. 题目描述 2. 思路分析 按题意模拟即可。 3. 代码实现 2829. k-avoiding 数组的最小总和 1. 题目描述 2. 思路分析 贪心 1~k-1中,选了1就不能选k-1;选了2就不能选k-2… 因此可以选1~k//2 剩余的从k开始向上选。 可以

    2024年02月11日
    浏览(34)
  • [LeetCode周赛复盘] 第 348场周赛20230604

    这场可惜了。 T1 模拟。 T2 模拟。 T3 倒序计算。 T4 同时限制上下界的数位DP。 6462. 最小化字符串长度 1. 题目描述 2. 思路分析 题意仔细想一下就会发现,其实会将每个字符仅留1个。 3. 代码实现 6424. 半有序排列 1. 题目描述 2. 思路分析 由于只能相邻交换来移动,因此每次只能

    2024年02月08日
    浏览(39)
  • [LeetCode周赛复盘] 第 111 场双周赛20230819

    T1 对向双指针。 T2 子序列/同向双指针。 T3 LIS/状态DP。 T4 数位DP。 2824. 统计和小于目标的下标对数目 1. 题目描述 2. 思路分析 类似两数之和,由于顺序无关,把数据排序。 设置l,r=0,n-1。 若a[l]+a[r]target,则a[l]+ 任意a[l+1…r]都target。则这r-l个数都可以和l组队。 3. 代码实现 2825

    2024年02月11日
    浏览(48)
  • [LeetCode周赛复盘] 第 102 场双周赛20230415

    T4卡了半小时,真的不应该。 T1 模拟。 T2 前缀和模拟。 T3 分层遍历。 T4 floyd/dij(我觉得dij不是正解)。 链接: 6333. 查询网格图中每一列的宽度 1. 题目描述 2. 思路分析 按题意模拟即可。 3. 代码实现 链接: 6334. 一个数组所有前缀的分数 1. 题目描述 2. 思路分析 不要被题目的一堆

    2023年04月16日
    浏览(42)
  • leetcode - 360周赛

     这道题的意思是,遇到 \\\"L\\\" 向左走,遇到 \\\"R\\\" 向右走,遇到 \\\"_\\\" 左右都可以走,那么要想找到距离原点最远的点,就是在找 | \\\"L\\\" + \\\"R\\\" | + \\\"_\\\"  代码如下:  这道题要我们求最小和,那么我们肯定是从1开始往后遍历,而且题目要求不存在两个不同的下标 i 和 j,使得 nums[i] + nu

    2024年02月09日
    浏览(46)
  • Leetcode周赛 | 2023-7-23

    01背包啊。01背包啊!怎么能一直往回溯上想!还是对动态规划太不熟悉了!这不就是01背包吗?还要别人提示才知道。 哈希,用双指针应该也可以。 也是动态规划啊!怎么能又想回溯!这道题如果两层遍历会超时,要保存前面遍历过的,当前点为奇数的最大值,和当前点为

    2024年02月16日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包