LeetCode---389周赛

题目列表

3083. 字符串及其反转中是否存在同一子字符串

3084. 统计以给定字符开头和结尾的子字符串总数

3085. 成为 K 特殊字符串需要删除的最少字符数

3086. 拾起 K 个 1 需要的最少行动次数

一、字符串及其反转中是否存在同一子字符串

 直接暴力枚举即可,代码如下

class Solution {
public:
    bool isSubstringPresent(string s) {
        bool vis[26][26]={0};// vis[x][y] 表示(s[i-1],s[i])是否出现过
        for(int i=1;i<s.size();i++){
            int x = s[i-1]-'a',y = s[i]-'a';
            vis[x][y]=true;
            if(vis[y][x])
                return true;
        }
        return false;
    }
};

// 用位运算优化
class Solution {
public:
    bool isSubstringPresent(string s) {
        int vis[26]={0};
        for(int i=1;i<s.size();i++){
            int x = s[i-1]-'a',y = s[i]-'a';
            vis[x]|=(1<<y);
            if(vis[y]>>x & 1)
                return true;
        }
        return false;
    }
};

二、统计以给定字符开头和结尾的子字符串的总数

这题就是纯数学题,就是要求我们找出特定字符的个数,然后从中选出两个组成子字符串,这题单一字符也符合条件,所以答案为n*(n-1)/2+n,n表示字符串中特定字符的出现次数

代码如下

class Solution {
public:
    long long countSubstrings(string s, char c) {
        long long n = count(s.begin(),s.end(),c);
        return n*(n-1)/2+n;
    }
};

三、成为K特殊字符串需要删除的最少字符数

仔细读完题目,你会发现这题其实和字符没多大关系,关键是频率,思路如下:

首先我们用freq[26]统计各个字符出现的次数(即频率),然后对freq进行排序,一共就26个字母的频率,我们可以暴力枚举以freq[i]为左端点,freq[i]+k为右端点的频率区间,在该区间内的字符不需要被修改,出现次数在该区间左边的字符要全被删除,出现次数在该区间右边的字符要被减少到freq[i]+k,枚举26次就能得到答案。

如何快速找到freq[i]+k对应的freq数组下标?用二分

如何快速得到前i个字符的出现次数?用前缀和

当然这题的freq数组不是很大,也就26个数,我们也可以直接遍历数组,不用二分+前缀和

代码如下

class Solution {
public:
    int minimumDeletions(string word, int k) {
        //统计频率
        int freq[26]={0};
        for(const auto&e:word)
            freq[e-'a']++;
        sort(freq,freq+26);
        int pre[27]={0};
        for(int i=0;i<26;i++) pre[i+1]=pre[i]+freq[i];
        int ans = INT_MAX;
        for(int i=0;i<26;i++){
            if(freq[i]==0) continue;
            int target=freq[i]+k;
            int l=i,r=25;
            while(l<=r){
                int m=l+(r-l)/2;
                if(freq[m]>target) r=m-1;
                else l=m+1;
            }
            ans=min(ans,pre[i]+pre[26]-pre[l]-target*(26-l));
        }
        return ans;
    }
};


class Solution {
public:
    int minimumDeletions(string word, int k) {
        int freq[26]={0};
        for(const auto&e:word)
            freq[e-'a']++;
        sort(freq,freq+26);
        int ans = 0;
        for(int i=0;i<26;i++){
            if(freq[i]==0) continue;
            int res = 0;
            for(int j=i;j<26;j++)
                res += min(freq[j],freq[i]+k);
            ans=max(ans,res);// 求能保持不变的最大字符数量
        }
        return word.size()-ans;
    }
};

四、拾起K个1需要的最少的行动次数

设 i 为Alice的站立位置的下标,j 为 1 所在位置下标

根据贪心,我们可以归纳出以下几个步骤(按照优先级排序):

a、拿 i 左右两边的1(如果 i 左右是1的话)--- 只需行动 | i - j | = 1次

b、执行操作1将maxChanges个1放在 i 的左边/右边,再执行操作2,拿到1 --- 只需行动2次

c、执行操作2将被 i 附近的1拿到 --- 需要行动 | i - j | >= 2

(如果 i 本身就是1,那么不需要操作就直接拿到一个1,该行动在代码中与步骤a和并了,可以暂不考虑)

如果需要拿出的K个1可以在前两个步骤之内完成,可以直接计算出答案(具体看代码)

否则,我们在前两步得到的x个1的基础上,再得到 K - x 个1即可,很多人都会有这样的思维惯性,但是这样是不正确的,因为步骤a和步骤c是密切相关的,我们在得到x个1时,就已经确定了Alice的位置,但是这个位置不一定是最优的,因为它还会影响步骤c,所以我们应该把步骤a和步骤c放在一起考虑,步骤b的操作次数单独计算。

如何计算步骤a和步骤c得到的 K - maxChanges 个1需要的最少操作次数?

其实观察它们的表达是| i - j | 我们就能知道,我们要求的是  K - maxChanges 个1 到达某个位置的最短的距离和,用中位数贪心【中位数贪心的证明如下】

代码如下

class Solution {
public:
    long long minimumMoves(vector<int>& nums, int k, int maxChanges) {
        int n = nums.size();
        vector<int>pos;
        // 求连续1的个数
        int mx = 0;
        for(int i = 0; i < n; i++){
            if(nums[i]==0) continue;
            pos.push_back(i);//记录1出现的位置
            int j=i++;
            while(i<n&&nums[i]){
                pos.push_back(i);//记录1出现的位置
                i++;
            }
            mx=max(mx,i-j);
        }
        
        mx = min(3,min(k,mx));
        if(mx+maxChanges>=k)
            return max(mx-1,0)+(k-mx)*2LL;// 只用步骤a/步骤a+步骤b的操作次数

        int size = k - maxChanges; // 步骤a+步骤c需要的1的个数
        int m = pos.size();
        
        long long pre[m+1]; pre[0] = 0;
        for(int i = 0; i < m; i++) pre[i+1] = pre[i] + pos[i];

        long long ans = LLONG_MAX;
        for(int i = 0; i + size-1 < m; i++){
            int l = i, r = i + size - 1;
            int m = l + (r-l)/2;// pos[m]是中位数
            long long left = 1LL*(m-l)*pos[m]-(pre[m]-pre[l]);
            long long right = pre[r+1]-pre[m+1]-1LL*(r-m)*pos[m];
            ans = min(ans, left+right);
        }
        return ans+2LL*maxChanges;
    }
};

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

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

相关文章

网络行为管理系统招标模板

项目名称&#xff1a;网络行为管理系统招标 一、项目背景 随着信息技术的迅猛发展&#xff0c;网络安全和数据保护已成为企业和组织面临的关键挑战。为了确保网络环境的安全、合规&#xff0c;并实现对网络行为的有效管理和审计&#xff0c;我们特此启动网络行为管理系统的招…

maya打开bvh脚本

目录 maya打开脚本编辑器 运行打开bvh脚本 maya导出bvh脚本 maya打开脚本编辑器 打开Maya软件&#xff0c;点击右下角 “脚本编辑器” 运行打开bvh脚本 https://github.com/jhoolmans/mayaImporterBVH/blob/master/bvh_importer.py import os import re from typing impo…

OD C卷 - 反射计数

反射计数&#xff08;200&#xff09; 给定一个包含0 、1的二维矩阵&#xff1b;一个物体从给定的初始位置出发&#xff0c;在给定的速度下移动&#xff0c;遇到矩阵的边缘则发生镜面反射&#xff0c;无论物体经过0还是1&#xff0c;都不影响其速度&#xff1b;经过t时间单位后…

学习次模函数-第2章 定义

纵观本专著&#xff0c;我们认为及其幂集&#xff08;即&#xff0c; 所有子集的集合&#xff09;&#xff0c;其基数为。我们也考虑一个实值集函数&#xff0c;使得。 与凸函数的一般约定相反&#xff08;见附录A&#xff09;&#xff0c;我们不允许函数有无穷大的值。 次模分…

文件包含一-WEB攻防-PHP应用文件包含LFIRFI伪协议编码算法无文件利用黑白盒

演示案例&#xff1a; 文件包含-原理&分类&利用&修复黑盒利用-VULWEB-有无包含文件白盒利用-CTFSHOW-伪协议玩法 #文件包含-原理&分类&利用&修复 1、原理 程序开发人员通常会把可重复使用的函数写到单个文件中&#xff0c;在使用某些函数时&#xff0c…

基于物理的实时渲染 -- PBR

简介 PBR&#xff0c;或者用更通俗一些的称呼是指基于物理的渲染(Physically Based Rendering)&#xff0c;它指的是一些在不同程度上都基于与现实世界的物理原理更相符的基本理论所构成的渲染技术的集合。正因为基于物理的渲染目的便是为了使用一种更符合物理学规律的方式来模…

面试题(二)

目录 21.JVM中哪些是线程共享区 22.你们项⽬如何排查JVM问题 23.⼀个对象从加载到JVM&#xff0c;再到被GC清除&#xff0c;都经历了什么过程&#xff1f; 24.怎么确定⼀个对象到底是不是垃圾&#xff1f; 25.GC Root 是什么? 26.JVM有哪些垃圾回收算法&#xff1f; 27.…

RabbitMQ 01

01.定义 02.功能

18个西语常用前置词用法大全,柯桥西班牙语培训

西语词类有九种&#xff1a;名词、冠词、形容词、代词、动词、副词、感叹词、前置词和连接词。 其中&#xff0c;“前置词”也就是我们俗称的“介词”&#xff0c;它是一种不变词类&#xff0c;本身没有独立的词汇意义&#xff0c;在句中与名词、形容词、动词等连用&#xff0…

BM43 包含min函数的栈(Stack)

import java.util.*; import java.util.Stack;public class Solution {Stack<Integer> s1 new Stack<Integer>();//存最小的元素Stack<Integer> s2 new Stack<Integer>();public void push(int node) {s1.push(node);if(s2.isEmpty() || s2.peek() &…

2024-03-23 问AI: 介绍一下深度学习中的ReLU函数

文心一言 ReLU&#xff08;Rectified Linear Unit&#xff09;函数是深度学习领域中常用的一种激活函数。它具有简单、计算高效且在某些情况下能有效缓解梯度消失问题等优点&#xff0c;因此在神经网络中得到了广泛的应用。 ReLU函数的定义非常简单&#xff0c;其数学表达式为…

Element Plus 基本使用

一、概述 1.1介绍 Element Plus 基本使用 element-ui 是基于vue 开发的一套ui组件库&#xff0c;提供丰富的网页开发组件&#xff0c;可用快速开发网站&#xff0c;降低前端开发成本版本 element目前有两个版本 element-ui&#xff1a;基于vue2element-plus: 基于vue3 官网地址…

2-dubbo源码 : 源码环境搭建

好的开始是成功的一半&#xff0c;阅读源码也是一样。 很多同学在下定决心阅读一个开源框架之后&#xff0c;就一头扎进去&#xff0c;迷失在代码“迷宫”中。此时&#xff0c;有同学意识到&#xff0c;需要一边 Debug 一边看&#xff1b;然后又有一批同学在搭建源码环境的时候…

鸿蒙一次开发,多端部署(十五)常见问题

如何查询设备类型 设备类型分为default&#xff08;默认设备&#xff09;、tablet、tv、wearable、2in1等&#xff0c;有多种查询设备类型的方式。 通过命令行的方式查询设备类型。 通过命令行查询指定系统参数&#xff08;const.product.devicetype&#xff09;进而确定设备…

Java基础-常用类

文章目录 1.Math类2.System类1.exit代码 结果2.arraycopy参数解释代码结果 3.currentTimeMillens代码结果 3.大数处理方案基本介绍BigInteger类介绍代码结果 BigDecimal类介绍代码结果 4.日期类对于IDEA类图中的属性![image-20240101190844530](https://img-blog.csdnimg.cn/im…

能降低嵌入式系统功耗的三个技术

为电池寿命设计嵌入式系统已经成为许多团队重要的设计考虑因素。优化电池寿命的能力有助于降低现场维护成本&#xff0c;并确保客户不需要不断更换或充电电池&#xff0c;从而获得良好的产品体验。 团队通常使用一些标准技术来提高电池寿命&#xff0c;例如将处理器置于低功耗…

RIPGeo代码理解(六)main.py(运行模型进行训练和测试)

​代码链接:RIPGeo代码实现 ├── preprocess.py # 预处理数据集并为模型运行执行IP聚类 ├── main.py # 运行模型进行训练和测试 ├── test.py #加载检查点,然后测试 一、导入各种模块和数据库 import torch.nnfrom lib.utils import * import argparse i…

162、应急响应——网站入侵篡改指南Webshell内存马查杀漏洞排查时间分析

文章目录 IIS&.NET—注入—基于时间配合日志分析Apache&PHP—漏洞—基于漏洞配合日志分析Tomcat&JSP—弱口令—基于后门配合日志分析查杀常规后门查杀内存马 需要了解&#xff1a; 异常检测、处置流程、分析报告等 网站被入侵会出现异常&#xff1a;流量异常、防护…

Git版本控制

这是两个学习Git推荐必看的文档&#xff0c;第一个链接是Git的官方权威文档&#xff0c;第二个链接是国内程序员在开发中&#xff0c;总结的Git快速入门教程&#xff0c;掌握这个&#xff0c;也足够应付在工作中的场景。 Git权威书籍《ProGit》中文版https://gitee.com/progit…

Web框架开发-Ajax

一、 Ajax准备知识:json 1、json(Javascript Obiect Notation,JS对象标记)是一种轻量级的数据交换格式 1 2 它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。…