当前位置: 首页 > web >正文

每日算法刷题Day21 6.3:leetcode二分答案2道题,用时1h20min(有点慢)

3. 2982.找出出现至少三次的最长特殊子字符串II(中等,学习)

https://leetcode.cn/problems/find-longest-special-substring-that-occurs-thrice-ii/

思想

1.给你一个仅由小写英文字母组成的字符串 s
如果一个字符串仅由单一字符组成,那么它被称为 特殊 字符串。例如,字符串 "abc" 不是特殊字符串,而字符串 "ddd""zz""f" 是特殊字符串。
返回在 s 中出现 至少三次最长特殊子字符串 的长度,如果不存在出现至少三次的特殊子字符串,则返回 -1
子字符串 是字符串中的一个连续 非空 字符序列。
2.单调性检验:长度越大,越不可能出现至少三次,而一旦满足条件,长度更小的一定满足条件
3.我的思想:用长度mid提取子串t,然后把用个函数判断是不是特殊字符串,函数逻辑是用unordered_set来判断,如果子串是特殊字符串,再用unordered_map来记录次数,判断是否大于3,但会超时
4.学习别人的思想:因为要判断某个字符的特殊子字符串出现次数,所以可以用unordered_map<char, vector<int>> mp; 先存储字符-长度数组,从而得到每种字符各自连续的子串长度,然后先遍历每种字符,此时的子串长度为x,如果x大于等于mid,那么就能得到x-mid+1个特殊字符串了,从而判断与3的大小,但因为每种字符是独立的,所以更新答案是res=max(res,mid)
5.学习分类讨论思想:
因为题目说明特殊字符串出现至少三次,那么就当三次来算,那么有哪些方法能够提取出三个特殊子串呢?可以考虑该字符子串的最长三个长度l0,l1,l2(满足l0>=l1>=l2)即可:

  • 从最长的l0取三个长度l0-2的子串
  • 从l0和l1取三个
    • l0=l1,取三个长度l0-1的子串(此时l0-1<l1)
    • l0>l1,取三个长度l1的子串(此时l0-1>=l1)
    • 所以合起来就是取长度min(l0-1,l1)的子串
  • 从l0,l1,l2取三个长度为l2的子串
    上面三种情况取最大的,即max(l0-2,min(l0-1,l1),l2),如果答案为0则说明不存在,返回-1
代码

c++:
学习

class Solution {
public:bool check(int mid, vector<int>& vec) {int cnt = 0;for (const int x : vec) {if (x >= mid) {cnt +=x - mid +1; // 字符串长度为k,最后一个开始位置x-mid,开始位置范围[0,x-mid]共x-mid+1个子串if (cnt >= 3)return true;}}return false;}int maximumLength(string s) {int n = s.size();int res = -1;unordered_map<char, vector<int>> mp; // 字符-长度for (int i = 0, j = 0; i < n; i = j) {while (j < n && s[i] == s[j])++j;mp[s[i]].emplace_back(j - i); //[i,j)}// 遍历每种字符for (const auto x : mp) {char c = x.first;auto vec = x.second;int left = 1, right = n - 2;while (left <= right) {int mid = left + ((right - left) >> 1);int cnt = 0;for (const int v : vec) {if (v >= mid) {cnt +=v - mid +1; // 最后一个开始位置v-mid,开始位置范围[0,v-mid]共v-mid+1个子串}}if (check(mid, vec)) {res = max(res, mid); // 因为遍历每种字符left = mid + 1;} elseright = mid - 1;}}return res;}
};

学习分类讨论:

class Solution {
public:int maximumLength(string s) {int n = s.size();int res = -1;unordered_map<char, vector<int>> mp; // 字符-长度for (int i = 0, j = 0; i < n; i = j) {while (j < n && s[i] == s[j])++j;mp[s[i]].emplace_back(j - i); //[i,j)}// 遍历每种字符for (const auto x : mp) {char c = x.first;auto vec = x.second;// 假设还有两个空串,确保能取到三个vec.emplace_back(0);vec.emplace_back(0);sort(vec.begin(), vec.end(), greater<int>()); // 降序排序res = max({res, vec[0] - 2, min(vec[0] - 1, vec[1]), vec[2]});}if (res == 0)return -1;return res;}
};

学习:max({})的{}是初始化列表,可以比较多个值

4. 2576.求出最多标记下标(中等)

2576. 求出最多标记下标 - 力扣(LeetCode)

思想

1.给你一个下标从 0 开始的整数数组 nums
一开始,所有下标都没有被标记。你可以执行以下操作任意次:

  • 选择两个 互不相同且未标记 的下标 ij ,满足 2 * nums[i] <= nums[j] ,标记下标 ij
    请你执行上述操作任意次,返回 nums 中最多可以标记的下标数目。
    2.单调性检验:下标数目越多,越不可能满足条件,所以存在一个最多下标数目,而一旦一个下标数目满足,那么比它小的肯定成立
    3.我的思想原来是排序完双指针(没写出来),右指针找到第一个满足2*nums[0]<=nums[start]的位置,但是会出错,因为其实是贪心思想,让[0,mid)[n-mid,n)(即最小的mid个和最大的mid个)配对,因为0和n-mid能配对,那么肯定能和大于n-mid的配对,但是是浪费
    4.学习同向双指针思想:
    还是右指针找到第一个满足2*nums[0]<=nums[start]的位置,但是此时匹配的时候左半部分只有满足2*nums[i]<=nums[j]的时候i才能自增,左边区间是连续的,为[0,i],所以答案就是i*2,但是右半区间不是连续的(原来认为连续),是for循环一直自增的
代码

c++:

class Solution {
public:bool check(vector<int>& nums, int mid) {int n = nums.size();//[0,mid)与[n-mid,n)配对for (int i = 0; i < mid; ++i) {if (2 * nums[i] > nums[n - mid + i])return false;}return true;}int maxNumOfMarkedIndices(vector<int>& nums) {int n = nums.size();sort(nums.begin(), nums.end());int res = 0;int left = 0, right = n / 2;while (left <= right) {int mid = left + ((right - left) >> 1);if (check(nums, mid)) {res = 2 * mid;left = mid + 1;} elseright = mid - 1;}return res;}
};

学习同向双指针:

class Solution {
public:int maxNumOfMarkedIndices(vector<int>& nums) {sort(nums.begin(), nums.end());int n = nums.size();int res = 0;// 从一半位置开始for (int j = (n + 1) / 2; j < n; ++j) { // 不是n/2// 满足条件拓宽左半区间if (2 * nums[res] <= nums[j])++res;}return 2 * res;}
};
http://www.xdnf.cn/news/10818.html

相关文章:

  • metersphere不同域名的参数在链路测试中如何传递?
  • 【MATLAB代码】制导——三点法,二维平面下的例程|运动目标制导,附完整源代码
  • 采摘机器人项目
  • dvwa5——File Upload
  • 1.6万字测评:deepseek-r1-0528横向对比 gemini-2.5-pro-0506和claude4
  • Cursor + Claude 4:海外工具网站开发变现实战案例
  • 基于PyQt5的相机手动标定工具:原理、实现与应用
  • 【Qt】构建目录设置
  • 从0开始学习R语言--Day16--倾向得分匹配
  • 相机--相机成像原理和基础概念
  • Cursor + Claude 4:微信小程序流量主变现开发实战案例
  • Springboot中Controller接收参数的方式
  • 功能管理:基于 ABP 的 Feature Management 实现动态开关
  • iptables常用命令
  • Spring Boot + MyBatis-Plus 读写分离与多 Slave 负载均衡示例
  • MyBatis 执行 SQL 报错:String 无法转换为 Long 的排查与解决实录
  • 【Linux内核】设备模型之udev技术详解
  • Unity异常上报飞书工具
  • 如何计算H5页面加载时的白屏时间
  • llama.cpp:纯 C/C++ 实现的大语言模型推理引擎详解一
  • 快速上手pytest
  • Java求职者面试:Spring、Spring Boot、Spring MVC与MyBatis技术深度解析
  • Kerberos面试内容整理-在 Linux/Windows 中的 Kerberos 实践
  • WPS word 已有多级列表序号
  • 2025年微信小程序开发:趋势、最佳实践与AI整合
  • Linux下使用nmcli连接网络
  • win11中使用grep命令
  • 若依+vue2实现模拟登录
  • JavaSec | H2数据库注入学习
  • DeepSeek 赋能智能建筑:区块链能耗管理的破局与革新