刷题小结(一)

记录下近期刷leetcode50题的心得和方法论小结。不过50题实在是不值一提,后续有机会继续刷,希望几年时间能多刷一些(flag,流汗)

一,方法论

1,双循环法
不考虑时间和空间的前提下,几乎所有题都可以用双循环甚至三循环进行求解
2,模拟
跟着题目所指进行直接模拟,通常会跟双循环结合,是比较符合人思维惯性的方法
也有一次循环依次遍历的
3,双指针
通常如果不能够新增空间,要求为O(1)会用到
通常有些反直觉,有三种形式,前后指针靠近,快慢双指针,条件双指针
前后靠近的双指针
快慢双指针
条件双指针是指两个指针是根据一定的条件进行变化的,不似前两者变化的是固定的
4,数据结构法
利用数据结构来规避一些操作例如查找,映射,存储,排序等
其实这个本质上就是利用数据结构比我们直接循环更快的特点。但是比如对于C这种根本没有数据结构的语言来说,没有区别。比如我们用map结构中的find功能,在C这里本质上可以用一个循环来替代。所以,个人以为数据结构实际上是一种取巧的做法,利用底层更快的原来来规避掉一个循环而已
5,双while法
从归并排序这里抽象出来的方法
何尝不是一种双指针
6,归并
个人觉得只在树相关的题目中使用,其余的通过可以用循环法来替代,当然也更加的难以理解
7,数学模拟法
没有统一性,基本是各个题目的具体情况具体分析
8,滑动窗口法
本质上也是双指针法,但是其根本是从双循环法演化而来,可以先用双循环暴力解,然后找出其中重复的部分,用滑动串口替代,滑动窗口与前文提到的双指针的不同之处和精髓在于其是同向移动不能相向靠近,窗口大小可以不固定。其实也可以理解为快慢指针的变种,只不过快慢指针的速度恒定,这里的速度会变化

二,载体

通常是数据结构
可以看作是题目中可以使用的载体,通常任何题目都可以根据数据结构进行划分。
一和二可以共用

三,分类

下面把近期做的题目分别做小结和分类
数组做载体穿插各种方法使用
1,合并两个有序数组
双循环
数据结构vector的插入
模拟,每次插入用一个循环模拟插入全过程,依次蠕动
逆向双指针:双循环需要用到额外数组,那直接利用原数组的多余空间就行
2,原地移除元素
条件双指针,一个指针照常动,另一个指针只有在不相等的情况下才动
3,原地删除有序数组中的重复项
条件双指针,关键点在于注意不相等时两个数的比较是不止差1个空间的,相等于上一条中的val值变成nums[p]
4,原地删除重复元素2
带次数限制的原地删除元素,与上面没什么区别,就是加一个计数器。或者也可以使得两个指针start和end刚好差次数
5,多数元素
数据结构法:找个数组或者map记录每个数出现的次数
双循环暴力法
排序法:这个有点反直觉,算是数学模拟法
6,轮转数组
双指针:分别指向两个位置,然后拼接,用到额外的数组
模拟法:双循环暴力模拟
数学法:数组翻转法
7,买卖股票最佳日期
经典模拟题,动态规划,可以记录最大最小值,遍历模拟计算
双循环暴力法:其实也是模拟。只不过重复了,可以用max,min来记录规避多余循环
前后双指针法:?没试过,也许可行
8,买卖股票最佳日期2
数学模拟法:理解加上所有增量就行
9,买卖股票的最佳日期三

10,跳跃游戏
数学模拟:边界不断拓展,依次遍历就行。
11,跳跃游侠2
模拟
或者数学上的解法:依次遍历记录位置区间,后续跳转,每个区间+1
简单来说就是不考虑直接跳到区间的,而是记录区间位置,等自己到记录的区间的位置
12,H指数
模拟,这个不太理解
13,双指针大类
验证回文
前后双指针
14,判断子序列
两个指针指向两个字符串依次对比
15,两数之和
先转换为递增序列,然后就可以利用排序后的特性来找,因为最大和最小在两边
看到排好序,就要利用其性质,就能想到双指针
16/盛最多水的容器
条件双指针的经典之作
17,三数之和,两数的基础上做就行,多一层循环

大类:数据结构
18、赎金信
直接map集合记录数据出现次数,需要注意的就是每个数只能使用一次

19.同构字符串
找对饮字符之间的映射关系,需要注意是一一对应,所以应该有两个映射表互相映射,因为对于数据结构map来说,key一定不同,值却可能相同

20.单词规律
同样的,先对字符串进行分割,而后一一对应,维护两个映射表

21,有效的字母异位词
排序对比最简单
其次还是map记录出现次数,然后双向对比

22、字母异位词分组
结合上面的,可以把上面的结果看作一个方法,然后依次遍历整个字符串数组,用一个map来记录,注意使用map最关键的就是想好到底要拿什么来当作key
key要有唯一性,所以这里就是把排序好的string当作key,然后就可以根据key来存储同分异构词
所以这里判断是否同分异构最好用sort,如果不用sort,每次都判断,则需要多设置1个循环,然后依次存入数组。

23、两数之和
利用map,key为值,val为下标
暴力双循环
双指针法:条件双指针

24、快乐数
用一个set来判断是否重复
快慢指针法:类似于链表判断循环

25、存在重复元素2
暴力双循环
map记录第一次出现的值的下标,然后找相同的值即可,还是记录下标的题

26、最长连续序列
最关键的就是怎么判断某个值是不是连续序列的第一个值就行,还有就是利用数据结构自动排列的特性,如果不用自动排序,那就依次查找num+1

链表:链表类题目一定画图,然后一般要设置一个头链表节点之前的节点
27、环形链表
快慢双指针:链表中很常用,因为链表都是通过指针来指示节点的
哈希表法,利用set

28、两数相加
链表中的两数相加:注意不要使用额外数做中间媒介,因为Int型有取值范围的,最好直接做一个新的链表,注意进位carry即可

29、合并两个有序链表
有点像双while循环的merger法

30、随机链表的复制
关键只在于链表中有一个随机指针需要复制,不要想太多复杂的方法,直接先复制一边无随机指针,然后再次遍历复制随机指针

31、反转链表2
有简到难,先想一下普通的反转链表怎么做。
在这里插入图片描述

链表类题目一定画图,然后一般要设置一个头链表节点之前的节点
然后再想想这里的部分反转链表怎么做,也是利用指针交替变化指向来做的
这是leetcode的图:
在这里插入图片描述

32、删除链表倒数第n个节点
删除指定节点:可以先遍历确定节点位置,然后进行删除
倒数的时候也可以想到栈的特性
也可以用双指针,说白了就是要定位到n的位置,那就用快慢指针,两个相差n,快指针到终点,慢指针到倒数n

33、删除排序链表中的重复元素
注意已排序的特性,另外这里是删除所有重复的,不是留下一个,不然可以直接用set
这里要用到条件中的循环:当我们找到重复元素的时候,需要设一个while循环,来找到下一个不重复的节点,这其实也算一个比较常用的套路:

 while (cur->next && cur->next->next) {
            if (cur->next->val == cur->next->next->val) {
                int x = cur->next->val;
                while (cur->next && cur->next->val == x) {
                    cur->next = cur->next->next;
                }
            }
            else {
                cur = cur->next;
            }
        }

作者:力扣官方题解
链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/solutions/678122/shan-chu-pai-xu-lian-biao-zhong-de-zhong-oayn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

34、旋转链表
这里先回忆一下选择数组怎么做,三种方法:找位置,数学反转,暴力模拟
链表这里同样的可以直接用双指针来找位置
官网给出另一种思路可以借鉴,算是链表特有的方法论:先闭合为环

35、分隔链表
说白了就是要把一个链表拆成两部分,再重新组合即可,多用几个链表指针,遍历,最后再重新组合

二叉树结构:一定要理解深度搜索递归法,广度搜索数列迭代法,先序、中序、后续遍历三种东西
我这里暂时只会深度搜索
递归需要注意好的几部分内容:一是边缘条件,不然会一直递归,二是返回值,三就是递归的参数
36、二叉树最大深度
深度递归,每次递归次数+1

37、相同的树
同样的,判断树是否相同,递归一个个判断

38、翻转二叉树
左给右边赋值,右边给左边赋值,然后翻转

39、对称二叉树
跟翻转不同,需要判断值是否相等,重点还是递归的时候顺序要正确
左数左和右树右比,左树右和右树左比较

40、构造二叉树:前序遍历和中序遍历
依然按照DFS进行构造,然后关键是要从两种遍历中找到一些关键信息,比如树的根,左树和右树等
前序遍历第一个数就是跟,对应到中序的位置,左边是左树,右边是右树,然后前序第二个是左树的root,依次类推
前序需要计算left_size,为什么,这里还需要进一步理解

41、构造二叉树:中序遍历和后续遍历
基于与上一题是反着的

数组拓展深入:
42,除自身以外数组的乘积
这题当时不会做,看了答案的巧思也不知道该归类到自己分类的哪个方案论里面。可能更接近于数学构思吧,就是构建一个数组来存储左积和右积,真的很巧妙

43,加油站
这题是不是有点像之前的某个链表题,就是先找一个点,然后再这个点的基础上再找一段距离,就是一个循环中间嵌套一个小循环,想到这个一点的话就比较容易模拟出来,算是模拟和双循环吧

44,分发糖果

45,接雨水

字符串
46,罗马数字转整数
这个唯一值得一提的就是可以做一个函数来简化一点点的代码,另外关键是用一个pre来优化cd md的表示,每次加的时候都是加prev,秒啊,模拟

47,整数转罗马数字
比上一题还简单,大胆的用Ifelse

48,最后一个单词的长度
倒着数就是了,注意特殊情况

49,最长公共前缀
横向数和纵向数,横向比较符合我们的通常思维,纵向可能会有一些反直觉,但是习惯了也还行,双循环法

50,反转字符串中的单词
先整体反转,再一个个反转,’ '就是分割符号。
但是这里遇到的问题是首位空格要去掉,这个稍微麻烦一点
官方解法这里可以使用双指针来简化代码,在原字符串的空间里构建新字符串

51,Z字形变换
这个不会,答案里面用到了数学规律,秒啊,理解了之后就很简单了,用一个扳机来回变动移动方向
根本来说就是把每一行都装进各自的字符串,最后拼接,用到字串数组数据结构

52,找出字串第一个匹配值的下标
str的实现,跟上面一提的思想有点像,条件嵌套循环,还是属于双循环+模拟

滑动窗口法:
53,长度最小的子数组:
可以先暴力双循环,再滑动窗口,核心和关键就是减少了双循环中的部分不必要的东西

54,无重复字符的最长子串
同上,只不过具体实现变了,end指针不能无脑++,重复的情况下不++;

滑动窗口拓展:
3. 无重复字符的最长子串
30. 串联所有单词的子串
76. 最小覆盖子串
159. 至多包含两个不同字符的最长子串
209. 长度最小的子数组
239. 滑动窗口最大值
567. 字符串的排列
632. 最小区间
727. 最小窗口子序列

四,心得

1,链表最重要的还是画图,把数据结构和指针的关系捋清楚就行,另外记住末尾指向空
2,树的深度有限搜索策略
3、stl数据结构的应用
4、双指针很常用
5、模拟法:理解题意是关键

  • 35
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值