LeetCode---390周赛

news2025/1/20 3:40:06

题目列表

3090. 每个字符最多出现两次的最长子字符串

3091. 执行操作使数据元素之和大于等于 K

3092. 最高频率的 ID

3093. 最长公共后缀查询

一、每个字符最多出现两次的最长子字符串

非常经典的滑动窗口问题,即动态维护一段区间,使得这段区间满足题目要求,代码如下

class Solution {
public:
    int maximumLengthSubstring(string s) {
        int cnt[26] = { 0 };
        int n = s.size();
        int ans = 0;
        for(int l = 0, r = 0; r < n; r++){
            cnt[s[r]-'a']++;
            while(cnt[s[r]-'a']>2){
                cnt[s[l]-'a']--;
                l++;
            }
            ans = max(r-l+1,ans);
        }
        return ans;
    }
};

二、执行操作使数据元素之和大于等于K

题目中有 将元素+1复制元素 两个操作。我们先来想想这两个操作哪个先执行,结果会更优?很显然,先+1再x2得到的结果 比 先x2再+1得到的结果 更大,即我们应该优先进行+1操作,然后开始复制得到的数最大,但是我们要加到多大再进行复制需要的操作次数才最小呢?我们可以暴力枚举出所有情况,然后取得最大值,代码如下

class Solution {
public:
    int minOperations(int k) {
        int ans = INT_MAX;
        for(int i=1;i<=k;i++){
            // 进行 i-1 次 +1操作
            // 再进行 ceil((k-i)/i) (ceil---向上取整) 次 复制操作
            ans=min(ans,i-1+(k-i+i-1)/i);
        }
        return ans;
    }
};

那有没有更加优雅的做法呢?

我们来看看i-1+(k-1)/i这个表达式,用x替换成i,得到 f(x) = x-1+(k-1)/x,问如何取f(x)的最小值?这个高中都学过,对勾函数,当x=sqrt(k-1)时,f(x)最小(如果不知道对勾函数,对它进行求导找最小值也是可以的)这里我们的x要取整数。代码如下

class Solution {
public:
    int minOperations(int k) {
        // 进行 x-1 次 +1操作
        // 再进行 ceil((k-x)/x) (ceil---向上取整) 次 复制操作
        // f(x) = x-1+(k-x+x-1)/x = x-1+(k-1)/x
        if(k==1) return 0; // 分母不能为零,要特判
        int x = sqrt(k-1);
        if(x*x==k-1) return x*2-1;
        else return min(x-1+(k-1)/x,x+1-1+(k-1)/(x+1));
    }
};

三、最高频率的ID

本题就是要求我们在统计ID出现次数的基础上维护出现频率的最大值 ,统计ID出现次数很简单,我们可以用哈希表存储,关键是如何维护出现频率的最大值,可以用multiset来帮助我们维护最大值,代码如下

// 哈希表 + multiset
class Solution {
public:
    vector<long long> mostFrequentIDs(vector<int>& nums, vector<int>& freq) {
        int n = nums.size();
        vector<long long> ans(n);
        multiset<long long> s;
        unordered_map<int,long long> mp;
        for(int i = 0; i < n; i++){
            int x = nums[i];
            auto it = s.find(mp[x]);
            if(it != s.end())
                s.erase(it);
            mp[x]+=freq[i];
            s.insert(mp[x]);
            ans[i]=*s.rbegin();
        }
        return ans;
    }
};

// 哈希表 + 堆(懒删除)  --- 可以了解一下
// 懒删除:当我们要取出堆顶元素的时候,看它的ID和freq是否匹配,
// 如果不匹配说明已经被修改,该数据无效 pop,如果相同,则是答案
class Solution {
public:
    vector<long long> mostFrequentIDs(vector<int>& nums, vector<int>& freq) {
        int n = nums.size();
        vector<long long>ans(n);
        priority_queue<pair<long long,int>> pq;//大堆<freq,ID>
        unordered_map<int,long long>mp;
        for(int i=0;i<n;i++){
            mp[nums[i]] += freq[i];
            pq.emplace(mp[nums[i]],nums[i]);
            while(pq.top().first!=mp[pq.top().second])
                pq.pop();
            ans[i]=pq.top().first;
        }
        return ans;
    }
};

 四、最长公共后缀查询

这题没啥可说的,之前周赛出过类似的,用字典树来做

代码如下

struct Node{
    Node* child[26]={0};
    int idx = -1;// 记录当前后缀下长度最短的字符串下标
};
class Solution {
public:
    vector<int> stringIndices(vector<string>& wordsContainer, vector<string>& wordsQuery) {
        // 建立字典树
        int pos = -1, mn = INT_MAX;
        Node*root = new Node;
        for(int i = 0; i < wordsContainer.size(); i++){
            const string &s = wordsContainer[i];
            int n = s.size();
            if(mn > n) pos = i, mn = n; // 找最短的字符串下标
            Node* cur = root;
            for(int j = n-1; j >= 0; j--){
                int x = s[j] - 'a';
                if(cur->child[x] == nullptr)
                    cur->child[x] = new Node;
                cur = cur->child[x];
                if(cur->idx == -1 || wordsContainer[cur->idx].size() > n)
                    cur->idx = i;
            }
        }

        // 查询
        int m = wordsQuery.size();
        vector<int> ans(wordsQuery.size(),-1);
        for(int i = 0; i < m; i++){
            const string &s = wordsQuery[i];
            int n = s.size();
            Node* cur = root;
            for(int j = n-1; j >= 0; j--){
                int x = s[j] - 'a';
                cur = cur->child[x];
                if(cur) ans[i] = cur->idx;
                else break;
            }
            if(ans[i] == -1) ans[i] = pos;
        }
        return ans;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构:Trie(前缀树/字典树)

文章目录 一、介绍Trie1.1、Trie的结点结构1.2、Trie的整体结构 二、Trie的操作2.1、Trie插入操作2.2、Trie查找操作2.3、Trie前缀匹配操作2.4、Trie删除操作 三、实战3.1、实现Trie&#xff08;前缀树&#xff09; 一、介绍Trie Trie 又称字典树、前缀树和单词查找树&#xff…

短视频素材那里来?五大平台让你的视频大放异彩!

哈喽&#xff01;短视频创作者们&#xff0c;是不是在寻找那些能让你的剪辑视频更加闪耀的素材&#xff1f;别着急&#xff0c;今天我要为你们带来五个超棒的视频素材网站&#xff0c;让你的作品在抖音、快手上大放异彩&#xff0c;成为众人羡慕的焦点&#xff01; 蛙学网&…

python电商结合双轨制

最近又重新整合翻看以前的数据&#xff0c;图片&#xff0c;绘画&#xff0c;还有各种编程代码&#xff0c;python,leetcode,还有关于商业方面的一些见解,想起了大学时候和同学们并肩作战&#xff0c;熬夜编码的时光。还有大数据&#xff0c;八爪鱼爬虫。 下面是我的手稿电商打…

输出单链表倒数第K个结点值

方法一&#xff1a; 两次遍历链表。第一次遍历&#xff0c;计算链表长度&#xff0c;然后计算链表倒数第m个结点的正数位置k&#xff0c;判断位置是否合法&#xff0c;如果不合法&#xff0c;输出NOT FOUND&#xff0c;否则&#xff0c;进行第二次遍历链表&#xff0c;查找链表…

【初阶数据结构】——牛客:CM11 链表分割

文章目录 1. 题目介绍2. 思路分析3. 代码实现 1. 题目介绍 链接: link 这道题是给我们一个链表和一个值X &#xff0c;要求我们以给定值x为基准将链表分割成两部分&#xff0c;所有小于x的结点排在大于或等于x的结点之前。 最终返回重新排列之后的链表的头指针。 2. 思路分析…

根据实例逐行分析NIO到底在做什么

Selector&#xff08;选择器&#xff09;是 Channel 的多路复用器&#xff0c;它可以同时监控多个 Channel 的 IO 状况&#xff0c;允许单个线程来操作多个 Channel。Channel在从Buffer中获取数据。 选择器、通道、缓冲池是NIO的核心组件。 一、新建选择器 此时选择器内只包含…

Python学习笔记-简单案例实现多进程与多线程

Python 的多进程与多线程是并发编程的两种重要方式&#xff0c;用于提高程序的执行效率。它们各自有不同的特点和适用场景。 多进程&#xff08;Multiprocessing&#xff09; 概念&#xff1a; 多进程是指操作系统中同时运行多个程序实例&#xff0c;每个实例称为一个进程。…

FA模型切换Stage模型组件切换之ServiceAbility切换DataAbility切换

ServiceAbility切换 FA模型中的ServiceAbility对应Stage模型中的ServiceExtensionAbility。Stage模型下的ServiceExtensionAbility为系统API&#xff0c;只有系统应用才可以创建。因此&#xff0c;FA模型的ServiceAbility的切换&#xff0c;对于系统应用和三方应用策略有所不同…

Java线程池工作原理浅析

为什么要用线程池&#xff1f; 1、线程属于稀缺资源&#xff0c;它的创建会消耗大量系统资源 2、线程频繁地销毁&#xff0c;会频繁地触发GC机制&#xff0c;使系统性能降低 3、多线程并发执行缺乏统一的管理与监控 线程池的使用 线程池的创建使用可通过Executors类来完成…

Clip算法解读

论文地址&#xff1a;https://arxiv.org/pdf/2103.00020.pdf 代码地址&#xff1a;https://github.com/OpenAI/CLIPz 中文clip代码&#xff1a;https://gitcode.com/OFA-Sys/Chinese-CLIP/overview 一、动机 主要解决的问题&#xff1a; 超大规模的文本集合训练出的 NLP 模…

vue属性与方法

vue属性与方法 计算属性v-model指令——表单的实现样式绑定 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…

前端面试拼图-数据结构与算法(二)

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1. 求一个二叉搜索树的第k小值 二叉树(Binary Tree) 是一棵树 每个节点最多两个子节点 树节点的数据结构{value, left?, right?} 二叉树的遍历 前序遍历&#xff1a;root→left→right 中…

Java类与对象:从概念到实践的全景解析!

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章专栏&#xff1a;javaSE的修炼之路 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 1、类的定义格式 在java中定义类时需要用到…

记录一个写自定义Flume拦截器遇到的错误

先说结论&#xff1a; 【结论1】配置文件中包名要写正确 vim flume1.conf ... a1.sources.r1.interceptors.i1.type com.atguigu.flume.interceptor.MyInterceptor2$MyBuilder ... 标红的是包名&#xff0c;表黄的是类名&#xff0c;标蓝的是自己加的内部类名。这三个都…

大话设计模式之工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种创建对象的最佳方式&#xff0c;而无需指定将要创建的对象的确切类。通过使用工厂模式&#xff0c;我们可以将对象的创建和使用分离&#xff0c;从而使代码更具灵活性和可维护性。…

Python之Opencv教程(1):读取图片、图片灰度处理

1、Opencv简介 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个用于计算机视觉和图像处理的开源库&#xff0c;提供了丰富的图像处理、计算机视觉和机器学习功能。它支持多种编程语言&#xff0c;包括C、Python、Java等&#xff0c;广泛应用于图像处…

Unity 学习日记 13.地形系统

下载源码 UnityPackage 1.地形对象Terrain 目录 1.地形对象Terrain 2.设置地形纹理 3.拔高地形地貌 4. 绘制树和草 5.为地形加入水 6.加入角色并跑步 7.加入水声 右键创建3D地形&#xff1a; 依次对应下面的按钮 || 2.设置地形纹理 下载资源包 下载资源包后&#x…

【微服务】软件架构的演变之路

目录 单体式架构的时代单体式架构(Monolithic)优点缺点适用场景单体式架构面临诸多问题1.宽带提速&#xff0c;网民增多2.Web2.0时代的特点问题描述优化方向 集群优点缺点适用场景搭建集群后面临诸多问题用户请求问题用户的登录信息数据查询 改进后的架构 垂直架构优点缺点 分布…

OSPF基本原理和概念

文章目录 背景知识OSPF协议概述&#xff1a;OSPF区域的表示OSPF 骨干区域 –区域0OSPF 非骨干区域 -非0区域OSPF的五种区域类型OSPF工作原理OSPF 的报文类型OSPF邻居表中的七个状态 总结 背景知识 一台路由设备如何获取其他网段的路由&#xff0c;并加入到路由表中 直连路由 …

【Java】LinkedList模拟实现

目录 整体框架IMyLinkedList接口IndexNotLegalException异常类MyLinkedList类成员变量(节点信息)addFirst(头插)addLast(尾插)在指定位置插入数据判断是否存在移除第一个相等的节点移除所有相等的节点链表的长度打印链表释放回收链表 整体框架 IMyLinkedList接口 这个接口用来…