【上分日记】第380场周赛(数位dp+ KMP + 位运算 + 二分 + 双指针 )

文章目录

  • 前言
  • 正文
    • 1.3005. 最大频率元素计数
    • 2.3007.价值和小于等于 K 的最大数字
    • 3.3008. 找出数组中的美丽下标 II
  • 总结
  • 尾序

前言

 本场周赛,博主也只写出两道题(前两道, hhh菜鸡勿喷),第三道涉及位运算 ,数位dp,第四道涉及KMP。 下面我们来总结一下这四道题。

正文

1.3005. 最大频率元素计数

 这道题不难,不过有一个比较妙的写法,因此还是来分析总结一下。

  • 题目链接: 最大频率元素计数
  • 题目思路:
  1. 用一个unordered_map更新次数。
  2. 更新出最大次数时,也更新ans的初始值。
  3. 当等于最大次数时,对ans 加上 当前最大次数。
  • 关键:最大次数的出现是呈现递增趋势的.
  • 因此我们可以一边记录unordered_map, 一边更新最大次数和answer。并且一个循环就可以更新出结果。
class Solution {
public:int maxFrequencyElements(vector<int>& nums) {int max_cnt = 0;int ans = 0;unordered_map<int,int> hash;for(auto e : nums){if(++hash[e] > max_cnt)max_cnt = ans = hash[e];else if(hash[e] == max_cnt)ans += max_cnt;}return ans;   }
};

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

  • 题目链接:价值和小于等于 K 的最大数字

  • 题目大思路:【数位dp】 / 【分类讨论 + 数学分析】 + 二分

  1. 数位dp
  1. 从高位开始枚举,一直枚举到最低位。
  2. 下一位的枚举的数字范围收到上一位的约束。
  3. 对不受到上一位约束的,采取记忆化的策略。受到上一位约束的,只有一种情况,无需记忆化。
  • 实现代码:
class Solution {
public:long long findMaximumNumber(long long k, int x) {//数位dpauto check = [&](long long num){//找其中为1 - num 上 x 的整数倍上 为 1的个数。//1.先将num转换为二进制数,到最高位即可。string s;for(int i = 0; i < 64; i++){if(num & (1ll << (63 - i)))s += "1";elses += "0";}long long dp[64][64];memset(dp,-1ll,sizeof(dp));/*其中dp表示为枚举第 i 位,之前之前已经有j个1时,数字出现1的总数1.limit表示第i位是否收到约束,即只能枚举 0 ~ s[i] - '0',如果收到,下一位也要收到约束,否则可以枚举 0 ~ 92.如果枚举第i位没收到约束,且之前j个1已经求过,则无需再求,即记忆化。反之,只会出现一次,没必要记忆化,当然记忆化也可以。*/function<long long(int,int,bool)> dfs = [&](int i ,\long long j,bool limit){if(i == 64) return j;else if(!limit && dp[i][j] != -1) return dp[i][j];long long res = 0;int end = limit ? s[i] - '0' : 1;for(int m = 0;  m <= end; m++){res += dfs(i+1,j + (m == 1 && (64 - i) % x == 0),\limit && (m == end));/*m == 1 且是x的倍数成立,结果位 j + 1,反之为 j如果当前位受到限制,且枚举之后的n也达到了end,则下一位受到限制。*/}if(!limit) dp[i][j] = res;return res;};return dfs(0,0,true);};//二分long long left = 0,right = k << x;//找靠近右边最大的num,因此要固定右边枚举左边。while(left < right){long long mid = (left + right + 1) / 2;if(check(mid) > k)right = mid - 1;elseleft = mid;}//必然会有答案。return left;}
};

说明:模版题——233. 数字 1 的个数

  1. 位运算 + 分类讨论
    在这里插入图片描述
class Solution {
public:long long findMaximumNumber(long long k, int x) {//位运算 + 分类讨论auto check = [&](long long num){long long ans = 0;int cnt = x - 1;for(long long i = num >> cnt; i; cnt += x,i >>= x){ans += (i / 2) << cnt;if(i % 2){long long mask = (1ll << cnt) - 1;ans += (num & mask) + 1;}}return ans;};//二分long long left = 0,right = k << x;//找靠近右边最大的num,因此要固定右边枚举左边。while(left < right){long long mid = (left + right + 1) / 2;if(check(mid) > k)right = mid - 1;elseleft = mid;}//必然会有答案。return left;}
};
  • 补充一点:这里的right 是 最多 num 能取到的数,设为上界,具体分析跟位运算的分析雷同,看奇数位且只看最低位,即 (num / 2x-1 - 1) / 2 == k,解出上界,取一个大于 num 的即可。当然如果不想这样写,也可以直接枚举最大值作为上界。

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

  • 题目链接:找出数组中的美丽下标 II

  • 题目大思路:KMP + 【二分】/ 【双指针】

  • 前置知识 ——【数据结构与算法】KMP算法
  • KMP模版
vector<int> kmp(string& text,string& pattern)
{//求next数组int tsz = text.size(),psz = pattern.size();vector<int> next(psz);int index = 0;for(int i = 1; i < psz; i++){char ch = pattern[i];while(index && ch != pattern[index]){//进行回退找最长匹配串与之匹配index = next[index-1];}if(ch == pattern[index])index++;next[i] = index;}vector<int> ans;//求子串的起始位置。index = 0;for(int i = 0; i < tsz; i++){char ch = text[i];while(index && ch != pattern[index]){index = next[index-1];}if(ch == pattern[index])index++;if(index == psz){//说明找到子串了,记录下标并进行回退ans.push_back(i + 1 - psz);index = next[index - 1];}}return ans;
};
  1. 双指针,因为要找 |j - i| <= k 的,所以我们固定 i找符合满足的 j 即可, 可以让j追i,当 j < i - k, 就让k++, 追上 i 或者 超过i 就停下。
  • 实现代码:
class Solution {
public:vector<int> beautifulIndices(string s, string a, string b, int k) {vector<int> res;vector<int> pos_a = kmp(s,a);vector<int> pos_b = kmp(s,b);int asz = pos_a.size(),bsz = pos_b.size();int j = 0;for(int i = 0; i < asz; i++){//让 j 追 i 且满足pos_b[j] < pos_a[i] - k, 就去追while(j < bsz && pos_b[j] + k < pos_a[i])j++;// 追上了,且满足情况if(j < bsz && abs(pos_a[i] - pos_b[j]) <= k)res.push_back(pos_a[i]);}return res;}
};
  1. 二分,也是固定 i , 二分找 j,因为pos_b存的是下标是递增的,因此可以二分找,我们可以找 大于等于 pos_a[ i ] 的第一个pos_b[ j ]pos_b[j - 1]可能是靠近pos_a[i]的其左边最近的那一个,对这两种情况进行讨论即可。
  • 实现代码:
   vector<int> beautifulIndices(string s, string a, string b, int k) {vector<int> res;vector<int> pos_a = kmp(s,a);vector<int> pos_b = kmp(s,b);int asz = pos_a.size(),bsz = pos_b.size();for(int i = 0; i < asz; i++){//二分找左边那个j  >= i 的最靠近的元素int left = 0,right = bsz - 1;while(left <  right){int mid = (left + right - 1) / 2;if(pos_b[mid] < pos_a[i])left = mid + 1;elseright = mid;}if(right >= 0 && pos_b[right] >= pos_a[i]){left = right - 1;}else{left = bsz == 0 ? -1 : right;right = bsz;}if( right < bsz && pos_b[right] - pos_a[i] <= k || left >= 0 && pos_a[i] - pos_b[left] <= k){res.push_back(pos_a[i]);} }return res;}
};
  • 这里的二分,要对结果判断一下是否有效,且这里 left是 pos_b 左边最靠近 pos_a[i ] 的,right 是 pos_b右边最靠近 pos_a[i]的。
  • 推荐双指针的写法。

总结

  1. 第一道题的一种遍历写法值得品味一番。
  2. 第二道题的数位dp + 位运算 需要认真思考。
  3. 第三道题的KMP算法 的线性复杂度值得探索。
  • 彩蛋:如果存在两个题目相同,可以先把简单的AC掉,然后用难的去简单的上测试,出错是不会罚时的哦!

尾序

我是舜华,期待与你的下一次相遇!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

江科大STM32 下

目录 ADC数模转换器DMA直接存储器存取USART串口9-2 串口发送接受9-3 串口收发HEX数据包 I2C(mpu6050陀螺仪和加速度计)SPI协议10.1 SPI简介W25Q64简介10.3 SPI软件读写W25Q6410.4 SPI硬件读写W25Q64 BKP、RTC11.0 Unix时间戳11.1 读写备份寄存器BKP11.2 RTC实时时钟 十二、PWR1…

[Linux 进程(四)] 再谈环境变量,程序地址空间初识

文章目录 1、前言2、环境变量2.1 main函数第三个参数 -- 环境参数表2.2 本地环境变量和env中的环境变量2.3 配置文件与环境变量的全局性2.4 内建命令与常规命令2.5 环境变量相关的命令 3、程序地址空间 1、前言 上一篇我们讲了环境变量&#xff0c;如果有不明白的先读一下上一…

【Kotlin】协程的字节码原理

前言 协程是Koltin语言最重要的特性之一&#xff0c;也是最难理解的特性。网上关于kotlin协程的描述也是五花八门&#xff0c;有人说它是轻量级线程&#xff0c;有人说它是无阻塞式挂起&#xff0c;有人说它是一个异步框架等等&#xff0c;众说纷芸。甚至还有人出了书籍专门介…

LabVIEW编码器自动校准系统

简介 在工作中&#xff0c;精确的角度测量和校准对于保持设备精度至关重要。开发了一套自动化角度编码器校准系统&#xff0c;利用了LabVIEW的强大功能。该系统以全圆连续角度标准装置为基础&#xff0c;配合二维导轨装夹系统&#xff0c;实现了空心轴角度编码器的高效自动校…

SQL Server 数据类型

文章目录 一、文本类型&#xff08;字母、符号或数字字符的组合&#xff09;二、整数类型三、精确数字类型四、近似数字&#xff08;浮点&#xff09;类型五、日期类型六、货币类型七、位类型八、二进制类型 一、文本类型&#xff08;字母、符号或数字字符的组合&#xff09; 在…

【FPGA Modsim】数字时钟

实验题目&#xff1a; 数字时钟设计 实验目的&#xff1a; 掌握数字时钟的工作原理&#xff1b;掌握使用数字逻辑设计集成开发环境分模块设计数字时钟的方法。 实验内容&#xff1a; 1、创建一个数字时钟工程…

【开发板资料】ESP32-S2-MINI-1开发板(源地工作室开发板)

最近买的开发板实在是太多了&#xff0c;一个一个盘算一下。 开发板为源地工作室售卖的源地ESP32-S2核心板&#xff0c;兼容ESP32-S2-DevKitM-1。 ESP32-S2-DevKitM-1 资料 引脚分布&#xff1a; 来源&#xff1a;ESP32-S2-DevKitM-1(U) - ESP32-S2 - — ESP-IDF Programmin…

第二百六十九回

文章目录 概念介绍设置方法示例代码内容总结 我们在上一章回中介绍了Card Widget相关的内容&#xff0c;本章回中将介绍国际化设置.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在这里说的国际化设置是指在App设置相关操作&#xff0c;这样可以让不同国家的…

x-cmd pkg | nping - 网络测试工具

目录 简介用户首次快速实验指南灵活性和可定制性提供多种网络模式功能强大满足各类网络测试需求相关作品竞品进一步探索 简介 Nping 是一个网络测试工具&#xff0c;用于生成网络数据包、分析响应以及测量响应时间。Nping 允许用户生成各种协议的网络数据包&#xff0c;用户可…

MySQL 从零开始:06 数据检索

文章目录 1、数据准备2、限制结果3、完全限定名4、排序检索 所谓数据检索&#xff0c;就是前面所讲的”增删改查“的”查“。 注&#xff1a;本文使用的“行”指数据表中的“记录”&#xff0c;“列”指数据表中的“字段”。 在第四节《表的增删改查》中已经介绍了 select 查询…

kafka之java客户端实战

1. kafka的客户端 Kafka提供了两套客户端API&#xff0c;HighLevel API和LowLevel API。 HighLevel API封装了kafka的运行细节&#xff0c;使用起来比较简单&#xff0c;是企业开发过程中最常用的客户端API。 而LowLevel API则需要客户端自己管理Kafka的运行细节&#xff0c;Pa…

Vim一键配置指南,打造高效率C++开发环境

文章目录 前言安装与卸载功能演示gcc/g升级问题 前言 Vim作为当下最受欢迎的文本编译器之一&#xff0c;不仅具有强大的文本编辑功能&#xff0c;还提供了高度的可定制性。用户可以根据自己的喜好自定义配置&#xff0c;并且通过自己编写插件或者使用现有的插件来扩展Vim的功能…