LeetCode---380周赛

题目列表

3005. 最大频率元素计数

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

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

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

一、最大频率元素计数

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

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

//两次遍历
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

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

简单说一下思路:先分别找出字符串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的最大数字

题目中出现小于等于求最大,一般是用二分 (对二分不了解的可以看看我之前写的二分查找详解),下面我们来分析一下,是否能用二分来做?即是否具有单调性。我们知道 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的个数,解析如下

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;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/338592.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录二刷 | 二叉树 | 把二叉搜索树转换为累加树

代码随想录二刷 &#xff5c; 二叉树 &#xff5c; 把二叉搜索树转换为累加树 题目描述解题思路递归法迭代法 代码实现递归法迭代法 题目描述 538.把二叉搜索树转换为累加树 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&…

【C++干货铺】C++11新特性——右值引用、移动构造、完美转发

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 左值与左值引用 右值与右值引用 左值引用和右值引用的比较 左值引用总结&#xff1a; 右值引用总结&#xff1a; 左值引用的作用和意义 右值引用的使用场景和…

C# Socket通信从入门到精通(17)——单个异步UDP服务器监听一个客户端C#代码实现

前言: 我们在开发UDP通信程序时,除了开发UDP同步客户端程序,有时候我们也需要开发异步UDP服务器程序,所谓的异步最常见的应用就是服务器接收客户端数据以后,程序不会卡在数据接收这里,而是可以继续往下执行,这在实际项目中是经常会遇到的,所以说掌握异步UDP服务器程序…

蓝桥杯省赛无忧 编程9

#include<bits/stdc.h> using namespace std; int main() {int n,k,ans0;cin>>n>>k;while(n--){int a;cin>>a;ansa&1;}if(ans&1) cout<<"Alice"<<\n;else cout<<"Bob"; return 0; }这个游戏是基于数…

Windows主机Navicat远程连接到Ubuntu18.04虚拟机MySQL

1. 在虚拟机上安装MySQL sudo apt-get install mysql-server sudo apt-get install libmysqlclient-dev 2. 检查安装 sudo netstat -tap | grep mysql 3. 查看默认密码 sudo cat /etc/mysql/debian.cnf 4. 用查看到的密码登录MySQL server&#xff0c;修改root用户的密码 …

OpenHarmonyOS-gn与Ninja

GN语法及在鸿蒙的使用 [gnninja学习 0x01]gn和ninja是什么 ohos_sdk/doc/subsys-build-gn-coding-style-and-best-practice.md GN 语言与操作 一、gn简介 gn是generate ninja的缩写&#xff0c;它是一个元编译系统&#xff08;meta-build system&#xff09;,是ninja的前端&am…

系统架构设计师教程(十三)层次式架构设计理论与实践

层次式架构设计理论与实践 13.1 层次式体系结构概述13.2 表现层框架设计13.2.1 表现层设计模式13.2.2 使用XML设计表现层&#xff0c;统一Web Form与Windows Form的外观13.2.3表现层中UIP设计思想13.2.4 表现层动态生成设计思想 13.3 中间层架构设计13.3.1 业务逻辑层组件设计1…

C++ | 五、哈希表 Hash Table(数组、集合、映射)、迭代器

哈希表基础 哈希表是一类数据结构&#xff08;哈希表包含数组、集合和映射&#xff0c;和前两篇文章叙述的字符串、链表平级&#xff09;哈希表概念&#xff1a;类似于Python里的字典类型&#xff0c;哈希表把关键码key值通过哈希函数来和哈希表上的索引对应起来&#xff0c;之…

对testfire.net进行信息收集,采用googlehacking语法,fofa等包括子端口号、子域名,备案信息,所属资产等等

采用被动的信息收集对testfire.net进行信息收集。 使用命令查询真实IP地址: nslookup testfire.net 使用googlehacking语法: 使用子域名查询网站查询一下子域名&#xff1a; 利用fofa查询一些信息&#xff1a; 利用whois 查找备案信息等&#xff1a; 尝试绕过千锋官网的cdn 利…

国考省考行测:选词填空,逻辑填空,语境分析,语意辨析,刷题,

国考省考行测&#xff1a;选词填空&#xff0c;逻辑填空&#xff0c;语境分析 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0…

【博士每天一篇论文-技术综述】Machine Learning With Echo State Networks 一篇系统讲解ESN知识的五星文章

阅读时间&#xff1a;2023-11-21 1 介绍 年份&#xff1a;2020 作者&#xff1a;徐元超&#xff0c;曼尼托巴大学 期刊&#xff1a; 无 引用量&#xff1a;无 这篇文章是一篇技术报告&#xff0c;从递归神经网络&#xff08;RNNs&#xff09;引入到回声状态网络&#xff08;…

基于DRIVE数据集的视网膜UNet分割

1 数据集介绍 这是一个非常小的数据集&#xff0c;非常适合用于视觉分割任务练手。数据集的文件夹如图所示&#xff1a; 图1-1文件夹结构 test中存放的是测试图片&#xff0c;training中存放的是20张用于训练的图片。imges文件夹中存放的是20张原始图片&#xff0c;mask中存放…

Leetcode的AC指南 —— 栈与队列:232.用栈实现队列

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列&#xff1a;232.用栈实现队列 **。题目介绍&#xff1a;请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a;…

解决 pnpm : 无法加载文件 C:\Program Files\nodejs\pnpm.ps1,因为在此系统上禁止运行脚本。

执行下面命令进行安装pnpm安装后 npm install -g pnpm 然后执行pnpm 报错 解决办法&#xff1a; 以管理员身份运行 Windows PowerShell &#xff0c; 在命令行输入以下命令后按回车&#xff0c; set-ExecutionPolicy RemoteSigned 再输入Y 回车即可。 再回到控制台输入p…

工作小记 cv-cuda使用

最近要实现RGB相关cuda算子的功能&#xff0c;最终通过自己手写核函数实现。这里记录一下对cv-cuda的调研和使用&#xff0c;因为项目要求gcc-5&#xff0c;而cv-cuda要求gcc11而放弃使用&#xff0c;但是相关的记录&#xff0c;以及使用方法都要记录下来&#xff0c;以便下次项…

在MD编辑器里插入20次方问题

前言 看了很多文章里面没写怎么插入20次方&#xff0c;最后在官网的一篇文章上看到了很详细的数学公式的插入。 问题 大家肯定以为这样就可以了 效果 明显是不行的 解决 使用{}把数字括起来就可以了。 1 20 1^{20} 120 小知识 在行内显示(就是与文字在一起) $ $另起…

《A++ 敏捷开发》- 5 量化管理从个人开始

我&#xff1a;你们管理层和客户都比较关心项目的进度&#xff0c;项目是否能按时完成&#xff1f;请问你们过去的项目如何&#xff1f; 开发&#xff1a;我们现在就是走敏捷开发&#xff0c;两周一个迭代。每次迭代前&#xff0c;我们聚一起开会&#xff0c;把所有用户故事按优…

互联网加竞赛 基于机器视觉的手势检测和识别算法

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势检测与识别算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…

(超详细)9-YOLOV5改进-添加EffectiveSEModule注意力机制

1、在yolov5/models下面新建一个EffectiveSEModule.py文件&#xff0c;在里面放入下面的代码 代码如下&#xff1a; import torch from torch import nn as nn from timm.models.layers.create_act import create_act_layerclass EffectiveSEModule(nn.Module):def __init__…

【Leetcode】277.搜寻名人

一、题目 1、题目描述 假设你是一个专业的狗仔,参加了一个 n 人派对,其中每个人被从 0 到 n - 1 标号。在这个派对人群当中可能存在一位 “名人”。所谓 “名人” 的定义是:其他所有 n - 1 个人都认识他/她,而他/她并不认识其他任何人。 现在你想要确认这个 “名人” 是…