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,一经查实,立即删除!

相关文章

贪心part2 买卖股票的最佳时机 跳跃游戏

122.买卖股票的最佳时机II 代码随想录 分析&#xff1a;计算相邻两天的收益&#xff0c;将正收益相加即为总的最大收益 class Solution:def maxProfit(self, prices: List[int]) -> int:res 0for i in range(len(prices)-1):if prices[i1] - prices[i] > 0:res prices…

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

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

人工智能方面顶会

人工智能 AAAI the National Conference on Artificial Intelligence 美国人工智能协会主办 IJCAJ the International Joint Conference on Artificial Intelligence每年举办 计算机视觉 CVPR IEEE Conference on Computer Vision and Pattern Recognition ECCV European Co…

【Python搞定车载自动化测试】系列文章目录汇总

系列文章目录汇总&#xff1a; 【Python搞定车载自动化测试】——PythonRobot Framework框架实现UDS诊断自动化&#xff08;含Python源码&#xff09; 【Python搞定车载自动化测试】——Python基于周立功ZCANPRO开发刷写脚本 【Python搞定车载自动化测试】——Python基于Pytest…

Opencompass模型评测教程

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

29. 相似矩阵,若尔当型

文章目录 1. 相似矩阵1.1 A T A A^TA ATA正定性证明 2. 相似矩阵2.1 举例2.2 证明相似矩阵具有相同特征值 1. 相似矩阵 假设矩阵A&#xff0c;B为正定矩阵&#xff0c;那么对于任意非零列向量x来说&#xff0c;二次型 x T A x , x T B x x^TAx,x^TBx xTAx,xTBx恒为正 x T A …

网络模型-策略路由配置

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

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

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

字符串转ArrayBuffer

const arrayBuffer new ArrayBuffer(str.length)const bufferView new Uint8Array(ab) for (let i 0; i < str.length; i) {bufferView[i] str.charCodeAt(i) }【前端】失落的 ArrayBuffer - 知乎

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

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

使用HTTP客户端在Python中进行网页抓取——笔记

使用HTTP客户端在Python中进行网页抓取 在网页抓取的上下中&#xff0c;HTTP客户端向目标网站发送请求&#xff0c;并检索网站的HTML代码或JSON有效负载等信息。 HTTP客户端并不直接指向代码开发者&#xff0c;而是指在客户端-服务器模型中发送HTTP请求的部分。这个客户端是一…

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

在信息化时代的浪潮中&#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人。具有博士学位的…

诺兰电影欣赏笔记

2012&#xff1a;蝙蝠侠&#xff1a;黑暗骑士崛起&#xff08;Batman 3: The Dark Knight Rises&#xff09; 播放平台&#xff1a;优酷

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…