Leetcode刷题笔记3
18. 四数之和
18. 四数之和 - 力扣(LeetCode)
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
解法一:排序 + 暴力枚举 + 理由set去重
超时
解法二:排序 + 双指针
[-2, -1, 0, 0, 1, 2] target
[ ] target - a
a
b [ ] target - a - b
left right
1. 先依次固定一个a;
2. 在a后面的区间内,利用“三数之和”找到三个数,使这三个数的和等于target - a即可
三数之和的大体思路:
1. 依次固定一个b;
2. 在b后面的区间内,利用“双指针”找到两个数,使这两个数的和等于target - a - b即可
处理细节问题:
1. 不重
去重a,b,left,right
2. 不漏
时间复杂度:O(N^3)
代码:C++
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ret;// 排序sort(nums.begin(), nums.end());// 利用双指针解决问题int n = nums.size();for(int i=0; i<n; ) //固定a{// 利用三数之和for(int j=i+1; j<n; ) //固定b{// 双指针int left = j+1, right = n-1;long long aim = (long long)target - nums[i] - nums[j];while(left<right){int sum = nums[left] + nums[right];if(sum < aim) left++;else if(sum > aim) right--;else{ret.push_back({nums[i], nums[j], nums[left++], nums[right--]});// 去重1while(left < right && nums[left] == nums[left - 1]) left++; //当left右移完之后和左边这个数相比,如果相同,说明重复元素,需要跳过while(left < right && nums[right] == nums[right + 1]) right--;}}// 去重2j++;while(j < n && nums[j] == nums[j - 1]) j++;}// 去重3i++;while(i < n && nums[i] == nums[i - 1]) i++;}return ret;}
};
209. 长度最小的子数组
209. 长度最小的子数组 - 力扣(LeetCode)
解法一:暴力枚举出所有子数组的和
时间复杂度:O(N^3)
R
[2, 3, 1, 2, 4, 3]
L
先定义一个sum,计算左区间的和
比如:sum + 2 + 3 + ...
这样可以省去再遍历一遍数组
R
[2, 3, 1, 2, 4, 3]
L
sum = 5
R
[2, 3, 1, 2, 4, 3]
L
sum = 6
len 2 -> 3
...
R
[2, 3, 1, 2, 4, 3]
L
sum = 12
len = 5
这个len是一直增长的,所以肯定不是最短的结果
接下来让L向左移动一位,然后继续让R从左开始移动
那这个时候从3开始的区间可以在上一个结果中找到
解法二:利用单调性,使用“同向双指针”来优化,也就是 滑动窗口
当使用暴力解法时。两个指针都可以做到不回退,都是向一个方向移动时就可以使用滑动窗口
1. 初始化;left = 0, right = 0
2. 进窗口
3. 判断是否是结果,然后更新结果(长度),再出窗口,判断len
2和3一直循环
以下是图解:
4. 为什么不往后枚举呢?因为已经知道接下来的情况再枚举也是白枚举,因为是正整数数组
利用单调性,规避了很多没有必要的枚举行为
5. 时间复杂度
进窗口要一个循环,判断也是一个循环,等于是两层循环套在一起
但是总的操作次数只是2n次
所以最终的时间复杂度是一个O(N)
代码:C++
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n = nums.size();int sum = 0, len = INT_MAX; //如果定义0,那最终的求min结果就是0,所以定义一个大的变量,不干扰最终结果for(int left = 0, right = 0; right < n; right++){// 进入窗口sum += nums[right];//判断要不要缩小窗口while(sum >= target){len = min(len, right - left + 1); // 更新结果sum -= nums[left++]; // 出窗口}// 一直更新到窗口不符合要求位置,然后right++}return len == INT_MAX ? 0 : len; // 如果没有最终结果就返回0,不然就返回len}
};
3. 无重复字符的最长子串
3. 无重复字符的最长子串 - 力扣(LeetCode)
子串和字数组都是连续的一段
解法一:暴力枚举 + 哈希表(判断字符是否重复出现)
可以借助哈希表来判断是否有重复字符
遍历的时候把字符保存到哈希表里,当遍历到重复元素时,停止这个操作
R
[d, e, a, b, c, a, b, c, a]
L
R
[d, e, a, b, c, a, b, c, a]
L
当a重复时,停止这个操作,然后移动L,
R
[d, e, a, b, c, a, b, c, a]
L
时间复杂度:O(N^2)
解法二:利用规律,使用“滑动窗口”来解决问题
R
[d, e, a, b, c, a, b, c, a]
L
R
[[d, e, a, b, c], a, b, c, a]
L
当a重复时,停止这个操作,然后移动L,
R
[[d, e, a, b, c], a, b, c, a]
L
当发现区间里面有重复字符时,可以让L先跳过这个重复字符
R也不用回到L的位置,让R继续移动即可
此时就可以使用滑动窗口解决问题
1. 先定义L = 0和R = 0
2. 进窗口 -> 让字符进入哈希表
3. 判断
根据判断结果判定是否出窗口(窗口内出现重复字符时才出窗口)
判断和出窗口是一个循环,一直到没有重复字符为止
出窗口就是从哈希表中删除该字符
然后更新结果(更新结果的过程要根据题目决定在哪)
本题中,在整个判断之后,更新结果
为什么要用滑动窗口,因为两个指针都不会回退
时间复杂度:O(N)
空间复杂度:O(1)
因为哈希表只有128位,所以可以忽略不计
代码:C++
class Solution {
public:int lengthOfLongestSubstring(string s) {// 下标表示字符,让里面的数来表示是否重复出现,出现一次为1,两次为2...int hash[128] = {0}; // 使用数组表示哈希表int left = 0, right = 0, n = s.size();int ret = 0;while(right < n){hash[s[right]]++; // 字符对应的下标,进入窗口while(hash[s[right]] > 1) // 判断{hash[s[left++]]--; // 先把哈希表里面的对应的值--,表示它从哈希表删除,然后++完成出窗口的操作}ret = max(ret, right - left + 1); // 更新结果,区间的长度是right - left + 1right++; // 让下一个元素进入窗口}return ret;}
};
1004. 最大连续1的个数 III
1004. 最大连续1的个数 III - 力扣(LeetCode)
最多k个0说明可以翻转0,1,2,...,一直到k个为止
比如下方这个例子中,k最多可以翻转100个0,但其实不需要翻转100次
[1,1,0,0,1,1,0], k = 100
[1,1,1,0,0,0,1,1,1,1,0], K = 2
[ ],最长为6
可以等价处理,在数组中满足0的个数不超过k次即可,只要这个区域的0不超过k,那么这个区域是一定可以翻转成功的
把原始问题转换成:
找出最长的子数组,0的个数不超过k个
解法一:暴力枚举 + zero计数器(int类型变量,统计0出现多少次)
R
[1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], K = 2
L
zero = 0
R
[1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], K = 2
L
zero = 1
R
[[1, 1, 1, 0, 0], 0, 1, 1, 1, 1, 0], K = 2 固定第一个位置的最优解
L
zero = 2
然后R继续从数组最开始的位置开始移动
解法二:滑动窗口
所以可以让R越过这段区域,不用重新遍历,可以移动L
R
[1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], K = 2
L
当在暴力枚举中L和R都只往一个方向移动时,可以使用滑动窗口
1. left = 0, right = 0
2. 进窗口 -> 如果是1,无视;如果是0,计数器+1
当R向后移动时就相当于进窗口了
当进入窗口时无视,当碰到0时,计数器加一
3. 判断 -> 当zero大于k,出窗口
出窗口
让L一直右移,直到窗口合法为止
当判断结束之后,更新结果,当R移动到最后位置就会得到最终结果
时间复杂度:O(N)
空间复杂度:O(1)
代码:C++
class Solution {
public:int longestOnes(vector<int>& nums, int k) {int ret = 0;for(int left = 0, right = 0, zero = 0; right < nums.size(); right++){if(nums[right] == 0) zero++; // 进窗口while(zero > k) // 判断窗口是否合法{if(nums[left++] == 0) zero--; // 出窗口,left向后移动} // 左闭右闭的区间ret = max(ret, right - left + 1); // 更新结果}return ret;}
};
相关文章:

Leetcode刷题笔记3
18. 四数之和 18. 四数之和 - 力扣(LeetCode) 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应&…...

初识C语言——第二十九天
数组 本章重点 1.一维数组的创建和初始化 数组的创建 注意事项: 1.一维由低数组在内存中是连续存放的! 2.随着数组下标的增长,地址是由低到高变化的 2.二维数组的创建和初始化 注意事项: 1.二维数组在内存中也是连续存放的&am…...
LeetCode27.移除元素
题目链接: 27. 移除元素 - 力扣(LeetCode) 思路分析:同样属于经典的双指针移动问题,要掌握固定的思路即可。 算法分析:这个题目可以这样处理,我们把所有非val 的元素都向前移动,把…...

DiffMap:首个利用LDM来增强高精地图构建的网络
论文标题: DiffMap: Enhancing Map Segmentation with Map Prior Using Diffusion Model 论文作者: Peijin Jia, Tuopu Wen, Ziang Luo, Mengmeng Yang, Kun Jiang, Zhiquan Lei, Xuewei Tang, Ziyuan Liu, Le Cui, Kehua Sheng, Bo Zhang, Diange Ya…...

ComfyUI简单介绍
🍓什么是ComfyUI ComfyUI是一个为Stable Diffusion专门设计的基于节点的图形用户界面,可以通过各种不同的节点快速搭建自己的绘图工作流程。 软件打开之后是长这个样子: 同时软件本身是github上的一个开源项目,开源地址为&#…...
【内存泄漏Bug】animation未释放
问题描述 一个页面做了动画特效,这个页面有可能跳转到其他页面,并长时间不返回,该页面此时已经不活跃了,该页面的对象为无用对象,存在内存泄漏风险 问题分析 这个activity的特性是 1. 有可能跳转到其他页面 2. 有可…...

《异常检测——从经典算法到深度学习》28 UNRAVEL ANOMALIES:基于周期与趋势分解的时间序列异常检测端到端方法
《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …...
Python正则模块re方法介绍
Python 的 re 模块提供了多种方法来处理正则表达式。以下是一些常用的方法及其功能介绍: 1. re.match() 在字符串的开始位置进行匹配。 import repattern r\d string "123abc456"match re.match(pattern, string) if match:print(f"匹配的字符…...
pdf使用pdfbox切割pdf文件MultipartFile
引入依赖: <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.25</version></dependency>测试代码: import io.choerodon.core.iam.ResourceLevel; impo…...

力扣HOT100 - 31. 下一个排列
解题思路: 数字是逐步增大的 步骤如下: class Solution {public void nextPermutation(int[] nums) {int i nums.length - 2;while (i > 0 && nums[i] > nums[i 1]) i--;if (i > 0) {int j nums.length - 1;while (j > 0 &&…...

设计模式 20 中介者模式 Mediator Pattern
设计模式 20 中介者模式 Mediator Pattern 1.定义 中介者模式(Mediator Pattern)是一种行为型设计模式,它通过封装对象之间的交互,促进对象之间的解耦合。中介者模式的核心思想是引入一个中介者对象,将系统中对象之间…...
在 C++ 中,p->name 和 p.name 的效果并不相同。它们用于不同的情况,取决于你是否通过指针访问结构体成员。
p->name:这是指针访问运算符(箭头运算符)。当 p 是一个指向结构体的指针时,用 p->name 来访问结构体的成员。 student* p &stu; // p 是一个指向 student 类型的指针 cout << p->name << endl; // 通过…...
C++基础:多态
多态相关 多态继承重写父类的虚函数多态的体现,父类的引用指向子类对象的空间虚函数可以实现,也可以不实现,不实现必须要有初始值存在未定义的虚函数的类为抽象类.抽象类不能实例化对象;(animal父类不能实例化对象)如果父类中的函数非虚函数,则会调用父类中的函数//多态的体现…...
移除元素(算法题)
文章目录 移除元素解题思路 移除元素 给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。…...

电商场景的视频动效
AtomoVideo:AIGC赋能下的电商视频动效生成本文分享阿里妈妈视频 AIGC(AtomoVideo等) 赋能视频广告创意的探索和实践。通过基于扩散模型的视频生成技术,结合可控生成技术,使静态电商图片能够栩栩如生地“动”起来,实现了在电商领域的视频 AIGC 应用落地。https://mp.weixi…...

Windows操作系统基本知识整理
目录 引言 一、Windows操作系统的发展历史 1.1 Windows 1.0到Windows 3.0 1.2 Windows 95到Windows Me 1.3 Windows NT到Windows 2000 1.4 Windows XP到Windows 7 1.5 Windows 8到Windows 10 二、Windows操作系统的核心组件 2.1 内核 2.2 文件系统 2.3 图形用户界面&…...
Vue 状态管理深入研究:Vuex 和 Pinia 的原理与实践对比
推荐一个AI网站,免费使用豆包AI模型,快去白嫖👉海鲸AI 👋 引言 在 Vue.js 应用程序中,状态管理是一个至关重要的方面。它有助于集中管理应用的状态,使组件之间的数据共享更加高效和可维护。Vuex 和 Pinia …...

【三数之和】python,排序+双指针
暴力搜索3次方的时间复杂度,大抵超时 遇到不会先排序 排序双指针 上题解 照做 class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:res[]nlen(nums)#排序降低复杂度nums.sort()k0#留两个位置给双指针i,jfor k in range(n-2):if nums[k]…...
TCP通信实现(服务端与客户端)
TCP通信实现(服务器端) 案例 // TCP 通信的服务器端#include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h>int main() {// 1.创建socket(用于监听的套接字)int lfd socket(AF_…...

安装appium自动化测试环境,我自己的版本信息
教程来自:Appium原理与安装 - 白月黑羽 我的软件的版本: 安装是选择为自己安装而不是选all user pip install appium-python-client命令在项目根目录下安装appium-python-client sdk的话最简单的安装方式就是去Android官网下一个android studio然后在…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...

Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
自定义线程池1.2
自定义线程池 1.2 1. 简介 上次我们实现了 1.1 版本,将线程池中的线程数量交给使用者决定,并且将线程的创建延迟到任务提交的时候,在本文中我们将对这个版本进行如下的优化: 在新建线程时交给线程一个任务。让线程在某种情况下…...