力扣hot100速览(1)

面向结果编程,全都采用最好理解的解法,但可能会有最优解(个人使用)

两数之和:

原理:

使用hash找另一半。类似于互斥?

解:

res=hash[current - target];如果存在就说明有另一半

字母异位词分组:

原理:

异位词排序之后相同,也可以用hash表比较

解:

排序得出key,然后放入hash,然后输出输出键相同的词。

最长连续序列:

原理:

找到连续序列的开头的数。

解:

存入set,然后遍历,查找每个数是否是连续序列的首个数字(判断之前是否有),然后遍历找到连续最长。

移动零:

原理:

一个指针找首个0.,一个指针遍历数字,数字跟0换。

解:

同原理

盛水最多的容器:

原理:

两条线之间的距离越大,可能的容积越大。但容积同时受限于较短线的高度。所以需要我们在缩距离的时候只缩最短的那根线。

解:

双指针,左右端开始缩

三数之和:

原理:

拎出来一个数,求剩下的数的两数之和

解:

排序,让数字有序,有助于我们求剩下的俩数。剩下的怎么求:双指针,和小了就缩左,大了就缩右。

接雨水:

原理:

想知道当前格子盛水多少,需要知道左边框的高度,自己的高度,右边框的高度。然后才能求水多深。但有些坑比较大的,所以要求当前块的左右边框高度还和周围最高格子有关系。

解:

从左往右遍历一次获取左边最大高度的列表,从右往左遍历获取右边最大高度的列表:

然后在遍历求得每个位置最大的水量。

无重复的最长子串:

原理:

无重复可以使用map来查重,因为是连续的,所以可以使用双指针来限定范围。这俩一组合就是滑动窗口。

解:

遍历,如果不重复加入map,如果重复就缩小左边,直至没有重复。

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

原理:

固定的滑动窗口大小,从左往右滑动判断

解:

滑动窗口,用hash或排序后比较来判断是否是异位词。

和为k的子数组:

原理:

pre[i]为从0到i的前缀和,k为目标和。

当pre[ i ] - pre[ j ] = k时,说明从j+1到i的子串的和是k。

解:

pre[ i ] - k  = pre[ j ] 时,符合条件。所以只要根据i 和 k 查找对应的 j 的个数,就可以知道和为k的组合有多少种。

我们把pre[ i ] 加入到hash表 hash[ pre[ i ] ]++,统计pre[ i ]出现的个数。那么结果就是 res += hash[ pre[ i ] - k ]; 

滑动窗口最大值:

原理:

主要是怎么求最大值。

解:

单调队列。pop时从左端只移除最大值,不是最大值就不动。push时,从右端加入,把小于当前数的值全pop出去。

所以队列最左端,就是最大值。

然后使用滑动窗口的方式push和pop即可

最小覆盖子串:

原理:

记录字母是否为有效字符。

解:一个map记录个数hashT,一个map负责管理窗口window。

右移窗口就是window[ s[ right ] ]++;

然后判断是否有效:如果window[s[right]] <= hashT[s[right]],则说明,window中该字母没填完,记录有效字母个数。

如果window[s[left]] > ht[s[left]],说明left不是有效字符,或者说是多了,说明可以移除,在window中移除该字母,且left++

当有效字符个数等于T的长度,说明就是一个有效的串,存起来。

最大子数组和:

原理:

暴力解法遍历所有子数组求解,所以我们用动态规划,dp[ i ]= dp[ i - 1 ]+ num[ i ];

解:

如果num[ i ]不是负数就带入公式,是负数就是当前的dp[ i ]=num[ i ]。之后遍历找出最大值即可。

合并区间:

原理:

没啥原理,左小于右就合,否则直接推入res

解:

排序,左小于右就合,否则直接推入res

轮转数组:

原理:

反转整个数组,然后反转前k个,再反转后k个即可得出结果

解:

同原理

除以自身意外的数组的乘积:

原理:

跟那个接雨水一模一样

解:

算从左向右乘的和,再算从右向左乘的和

缺失的第一个整数:

原理:

长度为n的数组,最多就是1-n,不在这个范围内的都不是。

解:

我们把不在这个范围内的都移动到外部。非原地算法就是重开一个数组,把没超出的数放到对应索引的位置。为了实现原地算法,我们把没超出的数字的对应索引给变成负数。哪里不是负数,就说明哪里是缺失的第一个整数,如果都是负数,那就是n+1。

矩阵置零:

原理:

记录哪行哪里有0,然后把行列置0。关键在怎么记录。

解:

用首行,首列记录该行该列是否有0;用两个变量记录首行和首列是否有0。遍历然后根据记录置0。

螺旋矩阵:

原理:

模拟,没啥原理,主要考察边界限制

解:

循环里转一圈就完事儿了。

旋转图像:

原理:

纯数学公式推导,对角线翻转(转置)然后逐行逆序。转置就相当于向左旋转90度,逆序就是翻转。

解:

令matrix[ i ][ j ]与matrix[ j ][ i ]交换,然后每行逆序。

搜索二维矩阵:

原理:

观察矩阵,以左下角元素为例,上面的小,右边的大。然后就可以z字型查找了。

解:

同原理

相交链表:

原理:

看图,

解:

双指针,一个遍历第一条然后遍历第二条,另一个遍历第二条然后再遍历第一条,指到同一个节点就是相交。

翻转链表:

原理:

从第二个元素开始,把元素加到头结点去(头插法)

解:

没啥解释的,现场分析现场做。

回文链表:

原理:

回文的链表正着遍历和倒着遍历一样

解:

同原理,比就完事儿了

环形链表:

原理:

快指针每次比慢指针快一个身位,所以总有一步他们会相交

解:

快慢指针,相交就是环

环形链表2:

原理:

参考GPT:

解:

快慢指针相交后,从头结点再出来一个指针,跟slow每次移动一个。

合并两个有序链表:

原理:

没啥原理,俩指针依次比较大小然后移动就可以了

解:

同原理

两数相加:

原理:

加法原理,记得进位

解:

没啥好解释,模拟加法运算过程就好了

删除链表的倒数第N个节点:

原理:

主要是链表没法反向遍历,为了解决这个问题我们需要一个可以反向遍历的方法。也就是栈。

解:

依次入栈,然后出栈N个,删掉最后一个出栈的元素。

两两交换链表中的节点:

原理:

同翻转链表

解:

魔改翻转链表的函数,传入一个反转的个数,记得反转完把上一组的指针指向新的头

K个一组翻转链表:

原理:

同上

解:

在两两交换链表中的基础上,限制如果传入长度不足k个,就不翻转的设定。

随机链表的复制:

原理:

关键是random怎么指,如果用下标方式指,比如记录当前k节点的下标是L,每次都要遍历查找L。我们可以使用hash来解决查找的问题,k节点映射到L节点。

解:

同原理

排序链表:

原理:

归并排序,但是,把值存到数组然后数组直接排,排好放回去,时间复杂度一样。

解:

同原理

合并k个升序链表:

原理:

两两合并,就完事了

解:

同原理

LRU缓存:

原理:

双向链表,为什么用双向链表呢,删除好删,能原地就删除

解:

模拟题目所说就行,删除用双向链表原地删除即可

二叉树的中序遍历:

原理:

左中右

解:

同原理

二叉树的最大深度:

原理:

深度优先遍历

解:

返回左右子树的最大深度。

翻转二叉树:

原理:

左右节点互换

解:

深度优先遍历然后交换左右节点

对称二叉树:

原理:

左节点的左等于右节点的右

左节点的右等于右节点的左

解:

递归比较即可

二叉树的直径:

原理:

一眼盯真,左右子树的最大深度和。

解:

递归求深度

二叉树的层序遍历:

原理:

一层一层的,这个没啥技巧,把节点放入队列,每次从队列拿出时,把左右节点放入队列。

解:

同原理

有序数组转换为二叉搜索树:

原理:

平衡,左右节点深度差不超过1;搜索树,左小于根,右大于根

解:

选择中间的数,剩下的放两边,依次递归

验证二叉搜索树:

原理:

左小于根,右大于根,但需要注意的就是需要传递该路径的最小值和最大值来限定右孙子不会大于爷爷。

解:

递归,每次都要传进来最大最小值限定就可以了。

二叉搜索树中第K小的元素:

原理:

中序遍历就是倒着输出的

解:

中序遍历k个节点就是答案

二叉树的右视图:

原理:

说人话就是每层最右的元素

解:

每次遍历一层的元素,最后一个就是结果

二叉树展开为链表:

原理:

内存很大,你忍一下,直接先序遍历存节点,然后建链表

解:

二刷再出原地算法

从前序和中序遍历构建二叉树:

原理:

原理简单,就是怎么把代码写出来难

解:

从前序遍历拿出首个节点,创建(创建节点);然后查找中序中该数的所在位置(查找该节点在中序的位置);把中序劈开分为左右的中序(分割);然后递归创建左右节点(创建左右节点),返回该节点。

路径总和3:

这哥们真是的表达了我现在的感受(无恶意)

 原理:

回溯思想,检查从任意节点开始,到它的任意子节点,是否他们的和为target

解:

前序遍历,每次遍历到一个节点,就递归获取该节点到任意子节点和为target的数目。

数目怎么求:每递归一次就减去当前值,作为下次比较的目标值。以此达到求多个节点和为target的目的。

二叉树的最近公共祖先:

原理:

查找左右子树是否含有目标p和q,如果都有,则就是结果,把该节点返回;如果有一个空,把不空的返回。

解:

同原理。

二叉树中的最大路径和:

原理:

和 路径总和3 类似,递归查找,以当前节点为拐点的路径的总和。

解:

用一个max存最大值,左+右+当前值 再比较max得出所有可能中的最大值。

岛屿的数量:

原理:

第一眼很容易蒙,看一遍题,一整片(连续)的1就算一个岛,所以我们只需要广度优先搜索,把岛给遍历一般,并且标记为访问过即可。

解:

遍历二维数组,每遍历到1并且没访问过就广度遍历把周围的全反问了,然后结果+1。

腐烂的橘子:

原理:

跟二叉树层序遍历一样。每次把周围的四个方向的橘子入队。

解:

同原理。

课程表:

原理:

拓扑排序,这个好难。

统计每个课程后续课程有什么,前置课程有什么。如果某个课程有前置课程,就上一层“锁”。学习某个课之后,把后续课程的“锁”解开一层。当锁解完了,就可以学了。

解:

先把 每个课程所需要学的前置课程的个数 和 每个课程的后置课程都存起来。

把所有不带锁的可成加入学习队列,然后依次学习。

当某个科目锁为0的时候,就加入学习队列。

最后统计有没有没学到的课。

前缀树:

原理:

没啥原理,这应该算一个数据结构,丢个链接看一下,代码就会写了。【数据结构 10】Trie|前缀树|字典树_哔哩哔哩_bilibili

解:

同原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值