Leetcode刷题笔记4

1658. 将 x 减到 0 的最小操作数

1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

如果想直接找到这些元素是比较困难的,所以:

正难则反

找到两个区域,a在左边,b在右边是的a + b = x。
[[    ]        [     ]]
   a             b
创建一个sum,sum是整个数组的和
这时可以考虑中间的这个区域,使得sum - x,使中间这块连续的区域最长

转化:找出最长的子数组的长度,所有元素的和正好等于sum - x
                                            len                                           target
n - len

解法一:暴力枚举

target = sum - x
  [ < target   ] R(>=target)
[                  ] ]             ]
  L

sum1 来标记L和R所指的区域的和
让R依次向后移动找那个最佳的位置

如果R找到一个元素使得前面的和 >= target,那么那个元素之前的元素之和肯定 < target

暴力解法的话,就让L右移一步,然后R回到L这里
但是R还有必要向左移动吗?
其实没有必要,本身前面的区域就小于target了,这时删除了第一个元素肯定还是小于target
所以R没有必要回去,所以让R要么原地不动,要么向后移动

解法二:滑动窗口

1.left = 0,right = 0

2.进窗口 -> sum1 += nums[right]

3.判断 -> 当这段区域的和 > target 就出窗口
出窗口 -> sum1 -= nums[left]

更新结果 -> 如果这段区域的和 = target 再更新结果

最后再用n减一下,得出最后结果

时间复杂度:O(N)
空间复杂度:O(1)

代码:C++

class Solution {
public:int minOperations(vector<int>& nums, int x) {int sum = 0; // 整个数组的和for(int a : nums) sum += a; // 把里面每个数都拿出来然后+=int target = sum - x;// 细节问题if(target < 0) return -1;int ret = -1; // 如果没有找到结果,返回-1,所以直接赋值-1for(int left=0, right=0, tmp=0; right < nums.size(); right++){// 进窗口tmp += nums[right];while(tmp > target) // 判断{tmp -= nums[left++]; // 出窗口}if(tmp == target) // 更新结果{ret = max(ret, right - left + 1);}}if(ret == -1) return ret;else return nums.size() - ret;}
};

904. 水果成篮

904. 水果成篮 - 力扣(LeetCode)

等于是连续摘

转化:找出一个最长的子数组长度,子数组中不超过两种类型的水果

fruits = [1,2,3,2,2]

解法一:暴力枚举 + 哈希表

[1,2,3,2,2]

比如固定1,那就只能找到1,2
如果固定2,可以采摘到2,3,2,2
...
找出所有可能性,然后选择最长的

可以借助哈希表储存水果类型,统计水果一共出现多少种

解法二:滑动窗口

比如:
      R
f = [1, 2, 1, 2, 3, 2, 3, 3]
      L
hash<int,int> 不仅要存入水果的种类,还要存入水果的数量
1. left = 0,right = 0

2. 进窗口 -> hash[f[Right]]++

3. 判断 -> hash.size > 2
出窗口 -> hash[f[Left]]--,要判断一下,如果对应的位置的元素变成0,要从哈希表中删除

更新结果

代码:C++

class Solution {
public:int totalFruit(vector<int>& fruits) {unordered_map<int, int> hash; // 统计窗口内出现了多少种水果int ret = 0;for(int left = 0, right = 0; right < fruits.size(); right++){hash[fruits[right]]++; // 进窗口while(hash.size() > 2) // 判断{hash[fruits[left]]--; // 出窗口if(hash[fruits[left]] == 0){hash.erase(fruits[left]); // 变成0就从哈希表中删除}left++;}ret = max(ret, right - left + 1); // 结果应该是left和right所指区间的长度}return ret;}
};

时间复杂度比较耗时,所以可以对哈希表做一个优化
 

// 优化后:
// 因为
//1 <= fruits.length <= 10^5
//0 <= fruits[i] < fruits.length
//所以可以使用一个数组来代表哈希表int hash[100001] = {0};
//
for (int left = 0, right = 0, kinds = 0; right < fruits.size(); right++)
if(hash[fruits[right]] == 0) kinds++; // 维护水果的种类
while (kinds > 2)
hash.erase(fruits[left]); -> if(hash[fruits[left]] == 0) kinds--;// 如果数据范围是有限的,可以使用数组来替代哈希表,比直接使用容器效率的提升很大

438. 找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

1. 暴力解法

1. 如何快速判断两个字符串是否是“异位词”
s1 = "aabca"
s2 = "abaca"

用排序然后再一一比较的方法太耗时了

所以可以利用哈希表
遍历s1的字符,把字符依次丢到hash1
遍历s2的字符,把字符依次丢到hash2
然后比较两个哈希表中对应位置字符出现的个数是否相等,相等就是异位词

2.解决问题
比如:
s = "cbaebabacd" 
以c为起点,找一个长度为m的子串,
把子串里面每个字符出现的个数丢到另一个哈希表hash2里面
然后遍历完这个子串之后,比较一下这两个哈希表是否相等就可以
然后以b为起点...

p = "abc",长度为m,hash1

hash1统计p里面的个数
hash2统计滑动窗口里面每个字符出现的个数

如何优化呢

每次枚举的时候,只需要把第一个字符删除,然后添加下一个字符就可以了
所以没有必要重新从头开始统计信息

s = "c b a e b a b a c d"
       L    R
s = "c b a e b a b a c d"
          L    R


解法:滑动窗口 + 哈希表

1. left = 0, right = 0

2. 进窗口 -> hash2[in]++

3. 判断 -> right - left + 1 > m,就移动
出窗口 -> hash2[out]--

更新结果 -> check(hash2, hash1)

优化:可以对更新结果的判断条件(check)进行优化
利用变量count来统计窗口中“有效字符”的个数

s = "ccbaebabacd",hash2

p = "abc",hash1: a -> 1, b -> 1, c -> 1

进窗口:进入后 -> 判断此时hash2[in]是否小于等于hash1[in]
如果小于等于,就是添加的有效字符,count++
如果是其余情况,就是无效字符,count不变

出窗口:出去前 -> hash2[out] <= hash1[out] -> count--
其余情况count不变

更新结果:count == m

代码:C++

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int hash1[26] = { 0 }; // 统计字符串p中每个字符出现的个数for(auto ch : p) hash1[ch - 'a']++; // ch - 'a'对应位置的下标int hash2[26] = { 0 }; // 统计窗口里面每一个字符出现的个数int m = p.size();for(int left=0, right=0, count=0; right < s.size(); right++){char in = s[right];//hash2[in - 'a']++; // 进窗口// 维护一下count,可以在hash2前面添加++if(++hash2[in - 'a'] <= hash1[in - 'a']) count++; // 进窗口+维护if(right - left + 1 > m) // 判断{char out = s[left++]; // 元素搞出去之后,left向右移动一步if(hash2[out - 'a']-- <= hash1[out - 'a']) count--; // 出窗口 + 出去前维护count//hash2[out - 'a']--; // 出窗口}// 更新结果if(count == m) ret.push_back(left);}return ret;}
};

30. 串联所有单词的子串

30. 串联所有单词的子串 - 力扣(LeetCode)

s = "barfoothefoobarman", words = ["foo","bar"] words里面的字符串长度都为3

s = "[bar][foo][the][foo][bar][man]"
          b     a     c     a      b     d

跟438. 找出所有字母的异位词 很像

滑动窗口 + 哈希表

不同之处:
1. 哈希表
hash<string, int> -> string对应字符,int对应字符串出现的次数

2. left与right指针的移动
移动的步长,是给定字符串里面每个单词的长度(len)

3. 滑动窗口执行的次数
len

代码:C++

class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {unordered_map<string, int> hash1; // 保存words 里面所有单词的频次for(auto& s: words) hash1[s]++; // 遍历字符串数组vector<int> ret;int len = words[0].size(), m = words.size();for(int i = 0; i<len; i++) // 执行len次{// 这个哈希表维护滑动窗口内面单词的频次unordered_map<string, int> hash2;for(int left=i, right=i, count=0; right + len <= s.size(); right+=len) // 因为是要把后面的字符串放到滑动窗口里面,如果right太靠后,后面根本就没有长度为len的字符串{// 进窗口 + 维护countstring in = s.substr(right,len);hash2[in]++;// 第一个哈希表不一定有这个单词,这样的话就会重新创建一个in,丢到哈希表// 所以会有时间消耗// 如果in出现在第一个哈希表里面的时候才接下来再判断// 因为此时判断的时候这个in一定是在里面了,所以就不用重新再创建一个in在哈希表里面了if(hash1.count(in) && hash2[in] <= hash1[in]) count++; // 可以提前判断一下,节省时间// 判断if(right - left + 1 > len * m) // len * m 窗口里面所有字符串的长度{// 出窗口 + 维护countstring out = s.substr(left, len);if(hash1.count(out) && hash2[out] <= hash1[out]) count--; // 有效单词hash2[out]--;// 出窗口后,left向后移动len步left += len;}// 更新结果,当有效字符的个数正好等于字典里面单词的个数时if(count == m) ret.push_back(left);}}return ret;}
};

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

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

相关文章

【CAN】STM32新能源汽车CAN通信实现过程

【CAN】STM32新能源汽车CAN通信实现过程 文章目录 前言一、软件1.PA11、PA12口配置2.PB8、PB9口配置 二、接线图三、硬件原理图四、上位机总结 前言 【电机控制】直流有刷电机、无刷电机汇总——持续更新 使用工具&#xff1a; 1.控制器——STM32F103C8T6 2.仿真器——STLINK …

Opencompass模型评测教程

模型评测 模型评测非常关键&#xff0c;目前主流的方法主要可以概括为主观评测和客观评测&#xff0c;主观评测又可以分为两种形式&#xff1a;人工判断或者和模型竞技场。客观评测一般采用评测数据集的形式进行模型评测。本教程使用Opencompass工具进行对Internlm2-7b模型进行…

网络模型-策略路由配置

在实际网络应用中&#xff0c;策略路由也是一种重要的技术手段。尽管在考试并不注重策略路由&#xff0c;但是实际上应用较多建议考生除了掌握基本的静态路由协议IP route-static&#xff0c;动态路由协议RIP、还要掌握如何配置策略路由。策略路由的基本原理:根据ACL定义的不同…

深度学习之人脸性别年龄检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 随着计算机视觉和深度学习技术的飞速发展&#xff0c;人脸性别年龄检测系统在多个领域展现出广…

SVG批量转为pdf超有效的方式!

最近在整理工作&#xff0c;发现ppt里面画的图智能导出svg格式无法导出pdf格式&#xff0c;由于在线的网站会把我的图片搞乱而且不想下载visio&#xff08;会把本地的word搞坏&#xff09;&#xff0c;因此琢磨出这种批量转换的方式。 1. 下载并安装Inkscape 下载链接&#xf…

电路仿真软件:点亮教学新篇章,十大便利助力高效学习

在信息化时代的浪潮中&#xff0c;电路仿真软件以其独特的优势&#xff0c;逐渐在教学领域崭露头角。它不仅能够帮助学生更好地理解电路知识&#xff0c;还能提升教师的教学效果。接下来&#xff0c;让我们一起探讨电路仿真软件对教学带来的十大便利。 一、直观展示电路原理 电…

Keras深度学习框架第二十四讲:KerasNLP概述

1、KerasNLP简介 KerasNLP是一个与TensorFlow深度集成的库&#xff0c;旨在简化NLP&#xff08;自然语言处理&#xff09;任务的建模过程。它提供了一系列高级API&#xff0c;用于预处理文本数据、构建序列模型和执行常见的NLP任务&#xff0c;如情感分析、命名实体识别和机器…

风控指南:国内车险欺诈呈现四大趋势

目录 车险欺诈呈现内外勾结的团伙化 防范车险欺诈需要多重合作 保险企业需要提升反欺诈能力 监管部门需要加强协同合作 2024年4月11日&#xff0c;国家金融监督管理总局官网发布国家金融监督管理总局关于《反保险欺诈工作办法&#xff08;征求意见稿&#xff09;》公开征求意见…

PCL平面多边形可视化

1、背景介绍 多边形是一个在二维平面上由直线段&#xff08;称为边或侧&#xff09;首尾顺次连接围成的封闭图形。这些直线段也称为多边形的边&#xff0c;而它们的交点称为多边形的顶点或角。在点云边缘点提取后&#xff0c;有时候需要将其进行可视化&#xff0c;如下图所示。…

【Mac】跑猫RunCat for mac(菜单栏Cpu可视化监测工具) v10.3免费版安装教程

软件介绍 RunCat是一款为菜单栏提供关键帧动画的软件。动画速度会根据Mac的CPU使用情况而变化。奔跑的小猫通过运行速度告诉您Mac的CPU使用率。 这是一款好玩的软件&#xff0c;可以为您的Mac使用添加一点小确幸。感兴趣的朋友可以试试哦。 安装步骤 1.打开安装包&#xff0…

贵州大学24计算机考研数据速览,国家重点实验室22408复试线285分!贵州大学计算机考研考情分析!

贵州大学计算机科学与技术学院坐落在贵州大学北校区&#xff08;贵阳花溪&#xff09;。 学院现有教职工139人&#xff0c;其中专职教师126人&#xff0c;教授17人&#xff0c;副教授37人&#xff0c;讲师46人&#xff0c;高级实验师4人&#xff0c;实验师17人。具有博士学位的…

Django 入门教程

1. Django简介 基本介绍 Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。 MVC 与 MVT 模型 MVC 模型 MVC 模式&#xff08;Model–view–controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&am…

图论(三)(最小生成树)

一、图的表示&#xff08;简要概述&#xff09; 对于图G&#xff08;V&#xff0c;E&#xff09;&#xff08; V 为节点的集合&#xff0c;E 为边的集合 V*V 的子集&#xff09;有两种表示方法&#xff1a;邻接链表和邻接矩阵&#xff0c;两种表示方法既可以表示有向图&#x…

【C++STL详解(四)------vector的模拟实现】

文章目录 vector各函数接口总览vector当中的成员变量介绍默认成员函数构造函数1构造函数2构造函数3拷贝构造函数赋值运算符重载函数析构函数 迭代器相关函数begin和end 容量和大小相关函数size和capacityreserveresizeempty 修改容器内容相关函数push_backpop_backinserterases…

基于open3d加载kitti数据集bin文件

前言 在自动驾驶领域&#xff0c;Kitti数据集是一个非常流行的点云数据集&#xff0c;广泛用于3D目标检测、跟踪和其他相关研究。Open3D是一个强大的开源库&#xff0c;专门用于处理和可视化三维数据。本文将介绍如何使用Open3D来加载和可视化Kitti数据集中的.bin文件。 准备…

工业路由器在工厂数字化的应用及价值

随着科技的飞速发展&#xff0c;数字化转型已成为工厂提高效率、降低成本、实现智能化管理的关键途径。在这个过程中&#xff0c;工业路由器凭借其独特的优势&#xff0c;正逐渐成为工厂数字化建设不可或缺的核心组件。本文将深入探讨工业路由器在工厂数字化中的应用及价值&…

linux与windows脚本格式必须转换,linux只有LF

如果windows下的脚本在linux下直接执行&#xff0c;则会造成无穷的错误。 在文本处理中, CR, LF, CR/LF是不同操作系统上使用的换行符. Dos和windows&#xff1a; 采用回车换行CR/LF表示下一行. UNIX/Linux &#xff1a; 采用换行符LF表示下一行. MAC OS &#xff1a; 采用回车…

《计算机网络微课堂》2-3 传输方式

本节课我们介绍几种传输方式&#xff1a; 串行传输和并行传输同步传输和异步传输单工&#xff0c;半双工‍‍以及全双工通信 ​​ ‍ 串行 我们首先来看串行传输和并行传输&#xff0c;串行传输是指‍‍数据是一个比特依次发送的&#xff0c;因此在发送端和接收端之间‍‍只…

Linux--09---RPM 、YUM

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 RPM1 什么是RPM2 RPM包的名称格式3.RPM查询命令4.RPM卸载命令5.RPM安装命令 YUM1 什么是YUMYUM优势1.自动下载RPM包并且安装2.自动处理依赖性关系&#xff0c;并且一…

【论文阅读】AID(ICCV‘23)

paper:https://arxiv.org/abs/2310.05666 code:https://github.com/YilongLv/AID Anchor-Intermediate Detector: Decoupling and Coupling Bounding Boxes for Accurate Object Detection