自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(143)
  • 问答 (1)
  • 收藏
  • 关注

原创 LeetCode394.字符串解码

题解的做法一和我第一种的思想是一样的就是从stack中拿出来字符串后乘以倍数又返回栈,但是它的的效率超过了77%,它相比于我就是一点优化,它stack放的是String而我放的是char,所以它遍历到一个字母字符后就把后面连串的字符拼接放进去。比如“3[a2[c]]”,一开始stack里面放的是3[a2[c,然后遇到了],就把c拿出来,把2*c放回去,现在stack里面是3[acc,然后又遇到了],把acc拿出来,把3*acc放回去,stack里面现在是accaccacc,遍历完了返回accaccacc。

2023-12-22 22:25:10 559

原创 LeetCode1143.最长公共子序列

如果text2的第i个字符等于text1的第j个字符,那么dp[i][j] = dp[i-1][j-1]+1,前i-1个配前j-1个的情况下+1。如果不相等,那么dp[i][j]=max(dp[i-1][j],dp[i][j-1]);我们建立一个二维数组dp,dp[i][j]表示拿text2的前i个字母和text1的前j个字母最多有几个公共子串。我们建立一个大小为[n1+1][n2+1]的数组,第0行或者第0列就都赋值为0。之前写过一道类似的动态规划的题,比这道题要复杂很多,

2023-12-14 21:48:07 508

原创 LeetCode5.最长回文子串

我们通过在字符串的两头和没两个字符之间加上#,这样无论奇数还是偶数长度的回文字符串都变成了奇数长度的回文字符串,比如aaba处理成#a#a#b#a#,偶数长度的回文字符串aa变成了#a#a#。如果i关于j的对称点2*j-i的臂长是n,那么位置i的臂长是min(n,2*j-i)。这个其实很好理解,因为j左右length拿一段是对称的,所以如果2*j-i有n的臂长按道理i也是这么大的臂长,但是只有length这一部分是对称的,而2*j-i的对称部分还可以向两边扩展,所以i的臂长只能取n和2*j-i的。

2023-12-10 20:34:11 939

原创 LeetCode208.实现Trie(前缀树)

它这个树的结构非常巧妙,节点Trie表示一个小写字母,每个节点都包含一个标致位boolean isEnd,表示这个小写字母是不是某个单词的结束字母,还包含一个节点数组Trie[] childern,children[0]表示‘a’..children[25]表示‘z’。通过构造方法我们可以看出,节点创建的时候它的isEnd是false,childre只是创建了一个数组容器,数组里面的节点是没有创建的。searchPrefix()方法作为一个辅助方法,作用是找到传进来的这个单词的最后一个字母。

2023-12-09 21:30:00 470

原创 LeetCode124.二叉树中最大路径和

这个非常好求,root为根的单向最大和路径就是(左子树为根的单向最大路径和右子树为根的单向最大路径中的最大的+root.val),当然如果两个子节点的最大和路径都是负数,那么root它自己单独就是最大的。dfs2(TreeNode root)方法是遍历整颗树的节点,找出分别以每个节点的最大和路径。(不是同时连左边和右边),然后用max是左右都连起来,max不停更新,最后返回max即可。这个也非常好求,要么是以root为根的单向的最大值。,要么是把根节点和左边最大的和右边最大的连起来。

2023-12-08 21:12:19 389

原创 LeetCode437.路径总和III

dfs方法中的参数sum表示从前面某个节点到上一个节点的和,拿这个sum加上当前节点的值如果等于targetSum那么答案数+1,然后可以把现在的sum往下面传递,也可以传一个0下去表示从下一个节点开始计算和,然后示例过了,测试用例没过,因为这样的话重复计算了多个答案,比如一个全右的树1,2,3,4,5,target=3,那么在dfs1的时候,传了sum等于0,然后dfs2的时候又传了sum等于0,然后dfs3,这条1,2,3的路径给算进去了,所以这样是不行的。中存放的是和为key的数量而不是节点。

2023-12-05 17:29:38 386

原创 LeetCode105.从前序和中序遍历序列构造二叉树

前序遍历也不难,前序遍历是根左右,preorder第0个数是根节点,后面是左和右,而我们在中序遍历中已经知道了左子树的长度leftLength和右子树的长度rightLength,所有从第1个数往后数leftLength就是左子树的前序遍历leftPreorder,剩下的就是右子树的前序遍历rightPreorder。然后需要注意的就是,递归的结束,如果左子树的长度小于0就不用递归的创建左子树了,右子树同理,最后返回root。大体上的思路就是这样,那么我们如何找出左右子树的前序和中序的遍历序列呢?

2023-12-01 22:37:57 466

原创 超实用!Spring Boot 常用注解详解与应用场景

注解用于标识一个类是 Spring MVC 控制器,处理用户请求并返回相应的视图。是一个通用的组件标识,可以用于标识任何层次的组件,但通常在没有更明确的角色时使用。注解也用于依赖注入,通常用在字段上,可以指定要注入的 Bean 的名称。注解用于标识一个类是业务层组件,通常包含了业务逻辑的实现。注解用于定义配置类,替代传统的 XML 配置文件。注解用于定义环绕通知,方法可以控制目标方法的执行。注解用于定义后置通知,方法在目标方法执行后执行。注解用于定义切面类,通常与其他注解一起使用。

2023-11-26 22:01:25 1587

原创 LeetCode198.打家劫舍

数组大小是n,我建立一个int[n][2]的dp数组,其中dp[i][0]表示不偷第i家能获得的最大的价值,dp[i][1]表示偷第i家能获得的最大的价值。max表是dp[i][0]和dp[i][1]中的最大值,表示偷到第i家能获得的最大价值(因为是从第0家偷到第n-1家的)。这个max是dp[i-1]的最大值,就是说如果我不偷第i家,那么第i-1家偷不偷都可以,所以不偷第i家的最大值就是第i-1家的最大值,与偷不偷i-1无关。

2023-11-26 20:51:35 614

原创 LeetCode78.子集

如果这个下标等于数组长度,说明数组中的所有元素都判断过了,可以把这个数组放进答案里了,但是我们不能把list放进去,因为这个list是全局的,dfs方法都在动这个list,后面的dfs会修改list,如果是放list,那么result里面就是全部一样的list并且是最后改完的list也就是空的list,因为最后一个递归是所有元素都是不添加的情况。所以用1左移i位就会得到一个只有第i位是1其他位是0的数,我们那么与的结果就取决于mask的第i位,如果第i位是0,那么每一位与的结果都是0,最终结果是0;

2023-11-25 22:54:18 607

原创 LeetCode207.课程表

看完题我就想,这不就是进程里面的死锁问题嘛,进程1等进程2释放锁,进程2等进程3释放锁,进程3等进程1释放锁,这就造成了死锁。数组表是节点的状态,visit[i]=0表示还没有搜索i节点(上图中没有颜色的节点),visit[i]=1表示正在搜索这个节点(上图中黄色的节点),已经搜索过的节点(上图中绿色的节点),然后。我记得的死锁的判断是用简化图的方式,先找出能最先完成的进程,然后把这个点消掉,再找在等待这个进程的进程里面最容易完成看看能不能消掉,消到最后不能消,如果有环就会死锁。题解用的是深度优先搜索。

2023-11-20 11:42:58 100

原创 LeetCode994.腐烂的橘子

于是我加了一个visit布尔数组,如果发现了一个2并且它没有visit才把它放进栈,然后visit改为true表示已经用它腐烂过周围了不能再次腐烂周围了,下次扫面到这个2就不会放进栈了,那么上面的情况就当第一个1变成2并且visit后就没有可以放进栈的2了,所以扫描一遍后stack还是empty,所以当扫描一遍后stack还是empty的话直接返回-1,如果没有2,永不腐烂,则返回-1),但是如果是一列2,2,1,0,1,1就出现死循环了,因为第一个1腐烂后无法去腐烂后面但是又始终hasFresh,

2023-11-18 22:44:14 270

原创 LeetCode200.岛屿数量

它是采用了一个内部类UnionFind,这个类有一个count属性,表示岛屿的个数,parent[]数组,大小就是giad的数组的大小,grid的每个元素都在parent中有对应的位置,也是采用序号的方式(行号*每行的个数+列号),比如grid[i][j]在parent中对应的下标就是parent[i*每行个数+j],它表示grid[i][j]有那个序号的元素连接而找到,通过。先用一个大的循环对grid数组遍历,去判断里面的元素grid[i][j]是不是一个岛屿。就可以找到序号i元素的最大祖先,然后通过。

2023-11-12 18:42:30 178

原创 LeetCode146.LRU缓存

put方法也是通过key拿到node节点,如果node不存在就创建一个node,然后把key和这个node放进hashMap,把这个node放到链表的头部,然后size++,如果这个时候size>最大容量了那么就把尾部节点删除,并且再map中删除这个key,size--;先讲get方法,如果map中没有这个key返回-1,如果有这个key,把lastUseMap中的这个key的value更新为本次操作的序号,再把序号加一,再把map中这个key的value返回。进行正真的putget缓存操作,然后用一个。

2023-11-11 21:04:55 917

原创 杂记杂记杂记

一句话理解ThreadLocal,threadlocl是作为当前线程中属性ThreadLocalMap集合中的某一个Entry的key值Entry(threadlocl,value),虽然不同的线程之间threadlocal这个key值是一样,但是不同的线程所拥有的ThreadLocalMap是独一无二的,也就是不同的线程间同一个ThreadLocal(key)对应存储的值(value)不一样,从而到达了线程间变量隔离的目的,但是在同一个线程中这个value变量地址是一样的。不存在多线程间共享的问题。

2023-11-11 16:18:14 107

原创 LeetCode148.排序链表

先创建一个哑节点,然后分别比较左右两个链表的头节点,最小的先移到哑节点后面,然后这个链表的指针移到下一个节点,下次比较就是这个链表的第2个节点和另一个链表的第一个节点,(因为两个链表都是已经排好序的,所以每次只要比较两个链表未放进去的最小节点即可),如果一个链表已经遍历完了,只要把另一个链表剩下的部分直接挂在后面即可。可以采用快慢指针的方法,快慢指针同时从头节点出发,快指针每次走两步,慢指针每次走一步,当快指针到达链尾,慢指针就在中间节点。然后利用递归的方法不断的分割链表,直到只剩两个节点,开始合并。

2023-11-08 15:25:26 751

原创 LeetCode24.两两交换链表中的节点

题解的第一种做法是使用递归,用head表示原始链表的第一个节点,新链表的第二个节点,用newHead表示原始链表的第二个节点,新链表的第一个节点。原始链表的其余节点的头节点是newHead.next,令head.next=swapPairs(newHead.next),表示将其余节点进行两两交换,交换后的头节点是head的下一个节点,然后令newHead.next=head,即完成了所有节点的交换,最后返回新链表的头节点newHead,第二种方法就和我的解法一样他管这个ans节点叫做哑节点。

2023-10-16 21:39:39 200

原创 LeetCode19.删除链表的倒数第N个节点

我记得我之前在剑指offer里面做过一道相同的题。

2023-09-18 22:50:18 198

原创 LeetCode2.两数相加

一看完题,我的想法是先算出这两个链表表示的数,然后相加,然后把这个数一位一位的分配给第三个数组,这种方法应该很简单但是要遍历三次数组,于是我就想直接一遍遍历,两个链表同时往后面遍历,把这两个数的和给第三个链表,如果有进位,下一个数加1;还是看看题解吧,题解的方法和我的方法差不多,但是它是用了一个判段是不是head来创建链表,然后拿到一个和就new 一个next节点并把和给它,然后当前指针移到他的下一个指针,如果遍历完了之后还有进位就再创建一个节点,并赋值1。

2023-09-16 21:53:07 270

原创 LeetCode142.环形链表-II

上一题一模一样,第一种解法用HashSet,第二种解法用快慢指针,可以看我的上一篇博客。看看题解有什么不一样的,没有任何不一样,和。

2023-09-12 19:02:44 164

原创 LeetCode141.环形链表

题解的第二种解法用的是快慢指针,就是用两个指针,一个跑的快一个跑的慢,快指针一定比慢指针先进入换中,等慢指针进入环中之后,由于他们速度不同,所以经过一定时间他们会相遇。

2023-09-11 19:25:30 166

原创 LeetCode54.螺旋矩阵

这道题一看好像在哪做过一样,好像是写剑指offer里面的状态机的时候写过类似的,就是定义4个方向,它就是按右,下,左,上的规律螺旋的,所以只要拿4个方向给他循环就可以,我是用一个表示方向的二维数组来表示方向。把这些操作放到一个循环里面,每遍历一个元素就把它放进答案并且把它对应的visited改为true,但是如何终止循环呢,通过记录访问到的元素的个数,如果等于矩阵中的元素的个数就退出循环,以下是我的代码。题解第二种做法是按层模拟,看完第二个题解我想起来了,我做过这道题。

2023-09-06 20:33:57 251

原创 LeetCode73.矩阵置零

看看题解,题解的第一种方法和我的差不多,但是他的感觉更容易理解,它没有拿两个set去记录要置零的行和列,而是拿两个boolean数组来标记(row标记行,col标记列),先第一遍遍历数组,对于遍历到的元素X,如果它等于0,就把两个标记数组中它对应的行和列改为true;

2023-09-05 20:23:21 396

原创 LeetCode41.缺失的第一个正数

如何设计这个标记呢?很巧妙,但是鬼想得到。对于一个长度为N的数组,未出现的最小正数只能出现在[N, N+1]中,因为如果[1,N]都出现了答案就是N+1,否则是[1, N]中未出现的最小正数,于是我们可以去遍历数组,对于遍历到的数x,如果x属于[1,N]就把数组第x-1个位置打上标记,如果数组中所有数都打上了标记,那么未出现的最小正数就是N+1,否者是最小的没标记的数。看看题解的正规解法,题解是真的非常的巧妙。

2023-09-04 21:47:28 320

原创 LeetCode189.轮转数组

这道题我先用最简单的方法做了一遍,就是先把后面的k个数放到一个数组先存起来,然后从数组的后面开始把前面的第k个数放过来,nums[i]=nums[i-k];然后前k个数就直接拿那个存的数组复制过来,然后就是注意如果k>nums.length,要把模上nums.length;

2023-08-30 20:56:14 177

原创 LeetCode56.合并区间

原理和我的算法是一模一样的,不一样的是他没有自己定义排序方法而是用了Array.sort()方法,然后重写compare()方法,比较数组中第一个元素也就是strat就可以,然后他也没用index来记录刚放进去的最新答案,而是通过merged.get(merged.size()-1)来获得这个刚放进去的最新答案。这道题我想了一会儿,实在想不到比较好的算法,只能硬着头皮写了,然后不断的debug,经过我不懈的努力,最后还是AC,不过效率确实低。

2023-08-29 22:40:30 412

原创 LeetCode239.滑动窗口最大值

队列里面存的不是数组的元素,而是一个大小为2的数组(其实有点像k-v键值对),数组第0个元素是参数数组nums中的值,第1个元素是这个值在nums中的下标,这样的话他就少了remove的一步,我是add一个就remove一个,这个是通过下标判断,如果队头这个最大的元素的下标在窗口的左边就直接poll,否则不用管,这样既少了每次remove而且poll的效率比remove还高,所以这个算法效率就更高了。我是没想到我用一遍for循环都能超时,然后我就想了下觉得没问题啊,我之前是这样做的啊。

2023-08-27 20:59:04 221

原创 LeetCode560.和为k的子数组

这道题我用的是暴力法,当然也是不断的提交不断发现问题改出来的,比如我之前是算到和大于目标值就break,其实不行因为后面还可以有负数,我把break删了。后面和为目标之后就答案+1然后break然后下一次遍历,测试用例中就出现了合理的子串后面还有一个0,于是我改成直到遍历完最后一个才结束循环;就是最简单的暴力法,用i,j两个指针作为子串的起点和终点,然后把子串的所有数的和加起来,如何等于k,ans++。

2023-08-25 21:16:32 294

原创 LeetCode438.找到字符串中所有字母异位词

他是创建两个大小位26的int数组scount和pcount,然后通过++sCount[s.charAt(i) - 'a'];统计字母出现的次数,然后也是通过窗口的特点,就是进来一个加上一个,出去一个减掉一个,所以可以发现,在第一次初始化完count数组后窗口不断右移,左边在把scount--,右边在把scount++。看了一下题解,题解为了更高的算法执行效率并没有用排序,而是统计窗口中所有字母出现的次数与模板中所有字母出现的次数进行比较,如果出现的次数相同,那字串和模板就是异位词。

2023-08-24 21:23:32 212

原创 LeetCode3.无重复字符的最长子串

但是题解和左右指针又不完全一样,它用的是滑动窗口,就是用一个Hashset作为一个滑动窗口,里面装了左右指针之间的这一段字符,如果左指针右移,那么hashset就要删掉左指针之前指的那个字符;可以发现最长字串起始位置递增的时候,结束位置也在递增,这是因为:假如我们选第k个字符为起始位置,第r个字符是它的结束位置,那么下次选择第k+1个字符为起始位置的时候,第k+1到r一定是不重复的,而且由于少了第k个字符,那么结束位置一定大于等于r,所以右指针不需要回去,

2023-08-23 20:35:31 478

原创 LeetCode42.接雨水

一直加到最后就是能加的水的高度,我想到了这里然后就想第i列的水其实就是第i-1列和i+1列中最小的高度减去第i列的高度,但是其实并不是,比如示例中的第5列,他的告诉是0左右两边是1,但水是2,然后看题解了。这个算法每次都要找出某一列左边的最高的柱子和右边的最高柱子,就多了一层循环,算法还可以优化,创建一个left_max数组和right_max数组,left_max[i]表示第i列左边的最高的柱子,right_max[i]同理。如果左右两边最高的柱子都比第i列的柱子矮的话,那么第i列能装的水就是0。

2023-08-22 21:17:23 216

原创 LeetCode283.移动零

【代码】LeetCode283.移动零。

2023-08-20 21:39:39 464

原创 LeetCode128.最长连续序列

他先把数组中的所有数全放进set里面,然后遍历set中的num,看看set中有没有num的前1个数num-1,如果没有,说明num就是一个序列的起点,把这个序列的长度先初始为1,然后用一个while循环去看看有没有num的下一个数,如果有的话,序列长度+1,num变为他的下一个数,没有的话循环结束,每次循环都更新longestStreak,最后返回longestStreak即可。说实话我看完也有点疑惑,外层这个循环已经是O(n)了,里面还有一个while循环,这不是超了吗?

2023-08-19 22:16:13 320

原创 LeetCode49.字母异味词分组

我一开始的思路就是用1个hashmap<Integer,List<String>>,Integer存的的是字符串所有字母ASCLL值的和,List里面放异位字符串,但是不是异位的字符串的ascll值也可能相同比如acd和abe,所以这个hashmap只能降低一点时间复杂度我还是要写一个方法来判断是不是异位字符串,就在我写的时候我突然意识到,这样的话hashmap的key会重复啊,我必须得想办法找到一个key使得异位字符串有相同的key其他没有。看了下题解的代码,太牛了,很简洁,他都没自己排序。

2023-08-18 22:16:55 208

原创 剑指offer44.数字序列中某一位的数字

我出问题的那个细节就是算end的时候我是用start+i位数的个数*i,这样就导致所有的end全算错了,除了2位数以外的start也全算错了,因为两位数的start是9+1得来的所以没算错,其他start是由上一个end得来的全错了,因为算n是第几位的时候减了start所以就错了,但是两个样例分别是3和11,3是1位数我直接返回了,11是2位数我的2位数start没错,所以两个样例都过了,示例没过。然后我们就拿n去循环中和area[i][0]和area[i][1],如果n在这中间,说明n是i位数。

2023-08-18 00:01:51 76

原创 剑指offer43.1~n整数中1出现的次数

我们知道,对于从 0 开始每 1000个数,「百位」上的数字 1都会出现 100次,即数的最后三位每 1000个数都呈现 [000,999]的循环,其中的 [100,199]在「百位」上的数字为 1,共有 100个。然后自己想了好多种方法,试了很多次都有没考虑到的地方,真的挺想自己做出来的,因为这道hrad题感觉没有那么难,但是写了一个多小时也没做出来,只好看题解了,题解的方法自己想到了一点点,就是去统计每一位上1出现的次数然后加起来,但是没把情况分明白。所以子只要遍历每一个k(0,1,2……

2023-08-16 22:45:55 75

原创 剑指offer62.圆圈中最后剩下的数字

也就是说当我们删除n个元素中第m%n个元素后,剩下的n-1个元素如果从第1个开始算,最后会剩下第x个元素,但是我们不是从第1个开始算的,我们是从第m%n个元素开始算的,所以最后剩下的是第m%n+x个元素,以防越界,最后再%n,也就是第(m%n+x)%n个元素,递归必须有终止条件,这道题的终止条件就是当n等于1的时候,返回第0个元素。然后自己又想了一会,没思路,就直接看题解了,题解这个递归都让我看了将近20分钟才看懂,但是看懂了就觉得好简单,没看懂就一直理解不了。

2023-08-15 23:37:37 161

原创 剑指offer57-II.和为s的连续正数序列

盯着15这个示例我就想到了,15的答案里面有3个的有5个的,所以我可以取寻找target的因数,这个因数就是其中一个答案的中间那个数,target除以这个因数你就可以知道有多少个数,比如3是15的因数,15是3的5倍,就可把3放在5个相邻的自然数中间这样就出来了,但是这样只能判断出包含奇数个自然数的答案,无法判断偶数个自然数的答案,比如15的7和8那个答案就判断不出,然后我又盯着这两个案例看,我发现如果target除以这个偶数n余数是n/2就可以,比如9%2=2/2;

2023-08-14 22:27:38 129

原创 剑指offer14-II.剪绳子II

通过a可以知道n里面有多少个3,所以最后的积就是a个3相乘,但是我每乘一次我都对p取一次余,得到最后的结果后我再对p取一次余(根据上面那个取余规则可知这样是合理的),然后就是讨论余数的问题,b是余数,如果余数是1,那么就拿a-1个3相乘最后乘以2个2也即是4;这道题和上一道题剪绳子I是一样的,只是数据的规模变大了,由上一题可知,要使得乘积最大就是要尽可能的把它分成全是3的段,如果绳子长度刚好是3的倍数就全部分成3,如果对3取余是2,那就把它分成一个2剩下的全分成3,如果余1就把它分成两个2剩下的全分成3。

2023-08-13 21:48:54 116

原创 剑指offer14-I.剪绳子

但是这样的话就会有重复,就是j和i-j后面会交换,而且这样会少一个i*1也就是说dp[j]也会少一个j*1,所以可以用dp[i] = j * dp[i-j],这样的话还漏了一种情况就是j*(i-j),因为dp[i-j]里面是没有(i-j)*1的,只有(i-j-1)*1,所以要把这种情况补上,也就是说当其中一个加数为j时的最大积是Math.max(j*(i-j), j*dp[i-j]),dp[i]的值是要把所有j都遍历完取其中的最大值。题解还有一种用高数解的,看完这个就知道为什么要分成2和3了。

2023-08-12 21:57:23 156

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除