算法刷题之三一维列表
1|0列表
列表和字符串是算法中最常见的数据结构,在列表中又分为一维列表和二维列表。一维列表的数据结构即使很简单也会有很多复杂的算法思想。
一维列表
- 删除排序数组中的重复项
- 移动非0元素到头部
- 盛最多水的容器
- 三数之和
- 长度最小的子数组
- 无重复字符的最长子串
- 前缀和
- 合并区间
二维列表
- 二维矩阵最大子矩阵和
- 旋转图像
- 杨辉三角
- 对角线遍历
- 矩阵元素查找
- 容器盛水
2|0删除排序数组中的重复项
题目:
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x2gy9m/
方法:只要将不同的数字全部集中到前面就可以了。设置双指针,慢指针用来指向列表前部分里不重复的下标,快指针向后遍历找不重复的数字。找到一个就让慢指针加1,然后将快指针指向的不重复的值赋值给慢指针。
双指针
:一种常用的,好用的数据处理方式。在快速排序中,将一个数组分成大小两个部分,用的就是双指针。
地道的写法:
3|0移动非0元素到头部
题目:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x2ba4i/
方法:将0全部集中到列表尾部,换一个思路就是将所有非0保持顺序,移动到列表前部。和上一题思想类似,使用双指针,慢指针指向0的下标,快指针向后寻找数值不为0的元素,交换快慢指针的数值,将所有0全部移动到尾部
思想:j遇到0元素不管,i遇到0元素停下。当j再遇到0元素时,和i的元素互相交换,最终完成将非零元素向前移动的目的
4|0盛最多水的容器
提示:
给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
链接:https://leetcode-cn.com/problems/container-with-most-water
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
方法:
首先想到的是暴力解法,两层循环能够找到任意两个柱子之间的距离,乘以高度,取最大值即可。时间复杂度为O(2),
然后使用双指针也能解决这个问题。以左右两边为边界向中间进发,比较两个柱子中较小的一个,并向中间移动,一直到两个柱子相遇。在这个过程中能够找到面积最大的那一对。
5|0三数之和
题目:
给一个数组[4,2,6,7,4,6],找到其中三个数的和为14的所有组合
方法
:
三数之和是使用双指针完成遍历,固定住第一个,然后使用双指针一头一尾向中间逼近
因为我们要同时找三个数,所以采取固定一个数,同时用双指针来查找另外两个数的方式。所以初始化时,我们选择固定第一个元素(当然,这一轮走完了,这个蓝框框我们就要也往前移动),同时将下一个元素和末尾元素分别设上 left 和 right 指针。画出图来就是下面这个样子:
当三个数的和大于0时,表明right需要左移以减少和,当小于0时,left需要右移,以增大和。
知识点
: 双指针配合循环
双指针小结
以上题目能力体现双指针的使用技巧,通常使用双指针,可以用在如下场景中:
- 从两端向中间迭代数组。
这时你可以使用双指针技巧:一个指针从头部开始,而另一个指针从尾部开始。这种技巧经常在排序数组中使用。
- 同时有一个慢指针和一个快指针。
确定两个指针的移动策略。与前一个场景类似,你有时可能需要在使用双指针技巧之前对数组进行排序,也可能需要运用贪心法则来决定你的运动策略。
6|0长度最小的子数组
题目:
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
方法:使用滑动窗户能够完美解决这个问题。窗口右端加入元素,判断窗口中元素总和是否大于target,如果大于计算长度,然后再左端缩小窗口,元素总和小于target,这是右端会继续向下滑动。
知识点
:变长滑动窗口
7|0无重复字符的最长子串
题目:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
方法:判断一个子数组中是否有重复有很多种办法:
- 使用暴力双层遍历
- 使用字典,判断某元素是否在字典中
- 使用数组,判断元素是否在数组中
方法:使用滑动窗解决:窗口左侧不断加入元素,判断元素是否存在于窗口中,不在则继续加入,在则将重复的元素去掉,继续添加。在这个过程中会有一个最大值出现。
知识点
: 变长滑动窗口
这一道题目还有更精彩的解法,滑动窗口不是只能用列表实现,还可以用字符串,双指针,字典等实现。
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/python-hua-dong-chuang-kou-xun-xu-jian-jin-de-3ge-/
滑动窗口小结
:
滑动窗口顾名思义就是对于序列取一段子序列,通常就是有一个大小可变的窗口,左右两端方向一致的向前滑动,右端固定,左端滑动;左端固定,右端滑动。
可以想象成队列,一端在push元素,另一端在pop元素,如下所示:
假设有数组[a b c d e f g h]
一个大小为3的滑动窗口在其上滑动,则有:
适用范围
1、一般是字符串或者列表
2、一般是要求最值(最大长度,最短长度等等)或者子序列
算法思想
1、在序列中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个窗口。
2、先不断地增加 right 指针扩大窗口 [left, right],直到窗口中的序列符合要求。
3、此时,停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的序列不再符合要求。同时,每次增加 left前,都要更新一轮结果。
4、重复第 2 和第 3 步,直到 right 到达序列的尽头。
思路其实很简单:第 2 步相当于在寻找一个可行解,然后第 3 步在优化这个可行解,最终找到最优解。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动。
8|0前缀和
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
输入:nums = [1,3,7,2,8]
输出:2,, [3,7] [2,8]
方法:
想要获取列表中一段子列表,使用双层循环就可以做到。能够获取到任意一段子列表,然后再将这一段nums[1:j]列表的和求解出来,这样时间复杂度会很高是O3,所以使用前缀和每一次内层循环时能够直接算出nums[i:j]的值。
知识点
:前缀和
其中的presum += nums[j]
就是前缀和,每次内层循环的和都记录下来,避免了计算nums[i:j]
但这种方式还不是最优,时间复杂度为O2,如果想要将时间复杂度降低到O,还需要使用字典这种方式。类似的解法是两数之和
使用一个字典维护前缀和与其出现的次数。
前3项的和为11,k=11。第一项和+sum(3,7) = sum(1,3,7),即sum(1) + 10 = sum(1,3,7),如果存在子数组sum=10,那么sum(1,3,7) - 10 就等于sum(1)。
即:sum(n) - k 在字典中,那么就说明有一个子数组=k
将两个数相加等于固定值,变成使用固定值-其中一个数=差值,判断差值在不在列表中
9|0合并区间
题目:
给出一组区间,请合并所有重叠的区间。
请保证合并后的区间按区间起点升序排列。
示例1
复制
[[10,30],[20,60],[80,100],[150,180]]
返回值
[[10,60],[80,100],[150,180]]
方法:区间问题两边都是极限,解决这一类问题需要固定住一端,然后对另一端判断并处理
知识点
:区间处理思想
10|0一维列表小结
对于一维列表的算法求解有很多中技巧,像上面提到的双指针
,滑动窗口
等。在这些技巧之下,需要对一维列表的最基础操作有深刻认识,那就是循环。下面来总结一下一维列表的循环有什么需要掌握的。
单层循环
:单层循环能取到列表中每一个值,这没什么特别的。
5 2 9 6 10 6
双层循环
:双层循环能对列表任意两个元素操作,比如两个元素之和,两个元素之积,甚至是两个元素中间元素的和。
5--5
5--2
5--9
5--6
2--2
2--9
2--6
9--9
9--6
6--6
双层循环使用的比较多,记住一点,双层循环能获取任意两个元素的组合。在这个最基础的操作之上再去看到一些技巧,技巧是对最基础解法的优化,所以对于一道题如果知道套路就上套路,不知道套路先用最暴力的解法,然后再往套路上靠。
__EOF__

本文链接:https://www.cnblogs.com/goldsunshine/p/14921440.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理