自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(49)
  • 收藏
  • 关注

原创 动态规划之单词拆分

当i = 4,j等于0,substring(0, 4)为leet,出现在字符串列表中,wordDict.contains(s.substring(j, i)结果为true,dp[j]即为dp[0],这时就涉及到dp[0]的初始化,如果初始化为false,导致dp[4]无法初始化,因此dp[0]初始化为true,因此dp[4] = true,可以判断了leet出现在字符串列表中,虽然是dp[4],但是仅判断了下标0到3,并没有包括下标4。注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

2024-05-29 09:26:04 1222

原创 动态规划之打家劫舍I和II

以上述示例说明代码的执行流程,首先dp[0] = 2,dp[1] = 7,dp[2] = max(dp[0] + nums[2], dp[1]) = max(2 + 9, 7) = 11,dp[3] = max(dp[1] + nums[3], dp[2]) = max(7 + 3, 11) = 11,dp[4] = max(dp[3], dp[2] + nums[4]) = max(11, 11 + 1) = 12。解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。

2024-05-24 09:02:56 932

原创 动态规划之递增子序列

因为题目要求连续,因此dp[i]仅能通过dp[i - 1]推出,易得dp[i] = dp[i - 1] + 1,以上述示例来看,for循环从下标1开始,即遍历元素3,3大于首元素1,dp[2] = dp[1] + 1,dp[2] = 2,5 > 3,dp[3] = 3,4 < 5,dp[4]保持初始化值为1,7 > 4,dp[5] = 2,显然连续最长递增子序列出现在dp[3],而不是dp[5],因此需要使用ans记录最长连续递增子序列的长度。输入:nums = [10,9,2,5,3,7,101,18]

2024-05-23 09:17:30 1115

原创 动态规划之不同路径I和II

其次,在计算dp[i][j]时,如果第i行和第j列本身是一个障碍,机器人无法到达该位置,所以没有必要计算该位置的dp[i][j]。其次是dp数组的初始化,观察递推式,dp[i][j]由其左侧和上侧的值计算得到,因此需要对dp数组的第0行所有位置和第0列所有位置进行初始化操作,由于机器人只能向右和向下走,因此到达第0行的某个位置,仅能通过一直右走得到,因此dp数组第0行所有元素初始化为1,同理,要想走到第0列的某个位置,仅能通过一直向下走得到,因此第0列所有元素的值都是1。输入:m = 3, n = 7。

2024-05-22 09:10:39 987

原创 完全背包之零钱兑换II

遍历到面值coins[i]时,如果存在一种硬币组合的金额之和等于 j−coins[i],则在该硬币组合中增加一个面额为coins[i]的硬币,即可得到一种金额之和等于j的硬币组合,举个例子,总金额为5,遍历到面值3,如果存在硬币组合的金额为5 - 3等于2,那么在该组合中添加面额为3的硬币,就可以得到金额之和为5的硬币组合,因此需要遍历coins数组,找出所有j - coins[i]的组合,相加就是总金额为j的所有硬币组合,得到。数组中的数字可以在一次排列中出现任意次,但是顺序不同的序列被视作不同的组合。

2024-05-21 10:15:17 1156

原创 完全背包之零钱兑换I

之后遍历面值5,当当背包容量j(总金额)为0,1,2,3,4时,不满足j >= coins[1],保持原值,j等于5,dp[5] = min(3, dp[5 - 5] + 1) = 1,dp[6] = min(3, dp[6 - 5] + 1) = 1 + 1 = 2,如此重复,得到dp数组如下,这里就不再展开说明,遍历完所有面值,返回dp[11]即为最终结果。这里钱币的面值即是物品的体积,也是物品的价值,面值有1,2和5,总金额为11,所以dp数组初始化为11。你可以认为每种硬币的数量是无限的。

2024-05-20 09:30:04 866

原创 回溯之电话号码的字母组合

首先定义map用来存储数字所对应的字母,定义ans用于收集结果,定义path用于收集递归for循环遍历加入的字母,如果path中的字母组合符合要求,将其加入ans中。在letterCombinations方法中将数字2-9及其对应字母存储到map中,之后调用backtracking方法收集所有可能的组合,最后返回ans。输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]问题,这次再分享一道利用回溯解决的leetcode题,下面先给出回溯的模板代码。

2024-05-18 09:29:54 937

原创 完全背包问题

背包容量刚好装下物品0,所以这里就解释为什么dp[0]要等于0,而不是其他值。接着遍历物品1,背包容量为1,2,3时,背包容量j都是小于物品1的体积,不进入if,背包容量为4时,等于物品1的体积,同时j - 物品1的体积刚好等于dp[0]等于0,不等于Integer.MIN_VALUE,所以dp[4] = 15,背包容量为5,6,7时,背包容量均有剩余,j - 物品1的价值等于Integer.MIN_VALUE,无法刚好装满背包,当背包容量为8时,dp[8] = dp[4] + 15 = 30。

2024-05-17 09:49:52 1420

原创 01背包优化

将一个数组分割成两个相同的子集,先判断数组和是否等于奇数,如果等于奇数,显然无法分成两个相等的子集,如果可以分成两个相等的子集,以上述示例为例,1 + 5 + 11 + 5等于22,可能可以分成子集和为11的两个数组,该问题就可以转化为背包容量为11,数组中元素相当于物品,物品的价值和体积均为数组元素的值,如果可以装满容量为11的背包,那么另一个子集元素和一定是11,因此最后只需要判断是否数组元素能够装满容量为11的背包。从01背包的递推公式。组合 2 和 1,得到 1,所以数组转化为 [1,1,1],

2024-05-16 09:29:23 1243

原创 01背包问题

当背包容量为5时,背包容量为j - vw[i][0],5 - 3 = 2,dp[0][2],表示剩余容量2,仅有物品0的最大价值,查上述表得10,即刚好放入物品0和物品1,最大价值为25。当背包容量为4时,放入物品2,背包容量为0,dp[1][0],剩余容量为0,有物品0和1,背包最大价值为0,因此价值为20,不放入物品2,价值为15,取最大价值为20,当背包容量为5时,放入物品2,背包剩余容量为1,无法放入其他物品,价值为20,和不放入物品2,价值为dp[1][5],25,取最大价值为25。

2024-05-15 10:48:35 934

原创 回溯之组合总和III

代码中首先定义了ans集合用于收集所有等于n的组合,path用于收集递归遍历过程中添加的元素,如果path中的元素组合符合要求,将path中的元素组合放入ans中,同时定义sum用于记录path中的元素和。找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:只使用数字1到9每个数字最多使用一次返回所有可能的有效组合的列表。该列表不能包含相同的组合两次,组合可以以任何顺序返回。解释:1 + 2 + 4 = 7,没有其他符合的组合了。,这次分享组合总和III,下面先给出回溯的模板代码。

2024-05-14 09:10:16 1174

原创 回溯之组合总和II

以上述示例说明代码的详细执行流程,首先定义ans集合收集所有符合条件的组合,path用于收集遍历过程中添加的元素,如果path中元素的组合符合条件,将其加入到ans集合中,定义sum表示path中元素和,定义used数组表示数组中元素是否在path中,combinationSum2中调用backtracking方法,最后返回ans集合。定义一个used数组,表示数组中的元素是否被使用,1表示被使用,0则没有被使用。使用回溯解决了组合总和I,这次使用回溯解决组合总和II,下面先给出回溯的模板代码。

2024-05-13 09:08:38 808

原创 回溯之组合总和I

给你一个无重复元素的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的所有不同组合,并以列表形式返回。首先定义ans集合用于收集符合要求的组合,定义path收集for循环遍历到的元素,如果path中所有元素的组合符合要求,将其放入到ans集合中。解释:2 和 3 可以形成一组候选,2 + 2 + 3 = 7。,这次分享leetcode上组合总和的第一道题,下面先给出回溯代码模板。输出:[[2,2,3],[7]]

2024-05-11 09:33:41 1177

原创 回溯之分割问题

首先定义了一个ans集合用于回收所有符合条件的分割子串,定义path用于收集遍历过程中分割出来的子串,如果path中子串都为回文串,则将其加入到ans中。在上述回溯代码中,关键部分在于使用了一个startIndex参数,规定了下一个递归截取的起始位置为当前递归方法遍历位置i的下一个位置i+1,需要注意的是,substring字符串截取方法截取区间是左闭右开,包含左侧,不包含右侧,因此要截取当前遍历位置i,右侧区间端点需要为i + 1。输出:[[“a”,“a”,“b”],[“aa”,“b”]]

2024-05-10 09:13:39 956

原创 回溯之全排列

之后第二轮for循环,将元素2加入path作为首元素,能够将[2, 1, 3]和[2, 3, 1]加入到ans集合中,第三轮for循环,将元素3作为首元素,能够将[3, 1, 2]和[3, 2, 1]加入到ans集合中,这里就不再详细描述。定义used数组,如果nums[i]在path中,则used[i]等于1,反之等于0。输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]输出:[[1,1,2], [1,2,1], [2,1,1]]

2024-05-09 09:18:27 1049

原创 回溯之子集

这题和上一题的问题的区别在于集合中的元素有重复,用题一中的解法就会出现重复的子集如示例给出的例子,用上一题解法得到[[],[1],[1,2],[1,2,2],[1,2],[2],[2,2],[2]],出现了两次[1, 2]。值得强调的是,由于子集中的元素无顺序要求,因此,[1, 2]和[2, 1]为同一个集合。输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]输入:nums = [1,2,2]

2024-05-08 09:42:45 1109

原创 回溯之组合

继续执行for循环,将元素3加入到path中,path为[3],递归进入下一个backtracking,startIndex为4,因此i等于4,将元素4加入到path中,此时path为[3, 4],递归进入下一个backtracking中,满足if条件,将[3, 4]加入ans集合,递归返回上一个backtracking,将元素4从path中移除,path为[3],此时for循环遍历结束,返回到最初的backtracking中,将元素3从path集合中移除,path为空。n 中所有可能的 k 个数的组合。

2024-05-07 09:24:44 1163

原创 二叉树之路径总和

递归返回,并进入结点11的right,将sum += 2,sum为22,将结点2加入list集合,list集合为[5, 4, 11, 2],接着if判断结点2是否为叶子结点,显然结点2为叶子结点,并且此时sum等于targetSum,重新创建一个集合将list中的所有值传入该集合,并放入ans中。递归进入结点2的left,为空,返回,递归进入结点2的right,为空,返回,结点2的左右子树遍历完成,sum -= 2,sum为20,将结点2从list中移除,list为[5, 4, 11]。

2024-05-03 16:02:20 2781

原创 二叉树之二叉搜索树I

结点1的left为空,递归返回。到根结点5,kth++,kth不等于3,进入根结点的right,进入结点6的left,为空返回,kth++,kth不等于3,进入结点6的right,为空,返回。递归进入结点1的right,结点1的right为空,递归返回,结点1递归返回。定义一个pre变量用于保存当前结点的前一个结点,在遍历的过程中比较前一个结点的值是否小于当前结点的值,由于采用中序遍历,如果是二叉搜素树,前一个结点的值必然小于当前结点值,因此如果大于,将isValid的值设为false,同时结束遍历。

2024-05-02 10:56:13 850

原创 栈操作之单调栈III

之后遍历元素1,此时栈顶元素2大于当前遍历元素1,需要将栈中大于1的所有元素对应的下标出栈,进入else,进入while循环,将栈顶下标1出栈,mid = 1,对应的值为2,i为2,对应的值为1,stack.peek()为0,对应的值为0,也就是左侧柱子高度为0,中间高度为2,右侧柱子高度为1,计算三根柱子围成的面积。此时stack为[0],对应的值为[0],由于0小于1,元素0不需要出栈,最后将元素1对应的下标压入栈中,stack为[2, 0],对应的值为[1, 0]。每个柱子彼此相邻,且宽度为 1。

2024-05-01 09:56:08 1284

原创 栈操作之单调栈II

之后遍历元素1,1小于2,对应下标压入栈中,此时stack为[4, 3],对应的值为[1, 2],之后遍历元素0,0小于1,对应下标压入栈中,此时stack为[5, 4, 3],对应的值为[0, 1, 2],之后遍历元素1大于0,所以需要将下标5出栈,mid等于5,值为0,i等于6,值为1,stack.peek()等于4,值为1。之后遍历元素1,进入else,将栈中所有小于1的下标弹出,stack中0下标对应的值为0,小于1,弹出,mid的值为0,stack为空,因此不会进入if判断中。

2024-04-30 09:49:54 852

原创 栈操作之单调栈I

之后遍历元素71,71小于栈顶元素75,将温度71下标压入栈中,得到stack为[3, 2],对应的值为[71, 75],继续遍历元素69,小于栈顶元素71,将69对应的元素下标加入栈中,得到stack为[4, 3, 2],对应的值为[69, 71, 75]。将76对应下标压入栈中,stack为[6],对应的值为[76],最后遍历元素73,73小于栈顶元素76,将73对应下标压入栈中,此时stack为[7, 6],对应的值为[73, 76]。ans初始值为[0, 0, 0, 0, 0, 0, 0, 0]。

2024-04-29 09:58:06 471

原创 两数、三数以及四数之和

如果这道题中的给定数组升序排列的,这道题还可以采用双指针来解决,定义left指针指向数组的起始位置,right指针指向数组的末尾位置,如果nums[left] + nums[right] > target,right指针向左移动一次,如果nums[left] + nums[right] < target,left指针向右移动一次,如果left >= right,还没有找到符合nums[left] + nums[right] = target的答案,直接返回[-1, -1]。

2024-04-26 07:27:04 1364

原创 栈操作首篇

之后是-3,stack直接压入-3,而对于helper,此时已不为空,需要比较压入栈的元素-3和栈顶元素的大小,将更小的加入栈中,-3显然小于-2,则将-3压入栈中。注意helper可以获取任意时刻栈的最小值,如压入-2后,栈中最小元素为-2,也是helper栈顶元素,压入4后,栈中最小元素为-3,也是helper栈顶元素,压入-5后,栈中最小元素为-5,也是helper栈顶元素。基本思路就是每次遇到左括号(‘(’,‘[’,‘{’),将其对应的右括号(‘)’,‘]’,‘}’)压入栈中。

2024-04-25 07:46:40 1056

原创 链表操作III

同时还需要满足一个要求就是快指针走过的路径是满指针路径的两倍,因为快指针每次走两步,慢指针每次走一步。换句话说,如果一个指针从链表头出发,一个指针从相遇点出发,那么从链表头开始走的指针走到入环点时,一定会与从入环点开始走的指针相遇,而此时从相遇点开始走的指针走过的路径长度为(n - 1)圈的环长加上相遇点到入环点的距离。这题的基本思路也是使用快慢指针,快指针每次走两步,慢指针每次走一步,当两个指针相遇时,重新让慢指针从链表头开始走,快指针从相遇点开始走,当两个指针再次相遇的位置即为入环位置。

2024-04-24 07:50:36 915

原创 链表操作II

以1->2->3->4->5->6->null为例子,要删除5这个结点,倒数第2个结点,fast先走3步,fast指向4,之后slow从1开始,fast从4开始,slow指向2,fast指向5,slow指向3,fast指向6,slow指向4,fast指向null。设链表为1->null,添加一个虚拟头结点-1->1->null。先给出链表结构的定义。如1->4->5->null,2->3->7->8->12->null两个升序链表合并结果为1->2->3->4->5->7->8->12->null。

2024-04-23 08:18:42 1015

原创 链表操作I

null条件跳出循环时,slow指针也就是慢指针就指向了链表的中间结点(如果结点个数为奇数个,slow就指向中间结点,如链表为1->2->3->4->5->null,slow最后就指向3,如果链表为偶数,如链表1->2->3->4->null,slow最后指向为2)。以1->2->3->2->1->null为例,第一步,得到slow指向中间结点3,将slow指向的下一个结点至尾结点进行反转,也就是将2->1->null反转为1->2->null这段。1->2->3->null不是一个回文链表。

2024-04-22 07:47:16 488

原创 二维数组之前缀和下篇

当i等于2时,值为-3,以下标1结尾的连续子数组和的最大值为1,-3 + 1 > -3,max = -2,ans = 1。子数组和的最大值,遍历到下标i时,求以下标i结尾的连续子数组和的最大值,就需要判断nums[i]可以单独成为一段,即以下标i起始的最大子数组和,还是需要加上前面f(i - 1)那一段,而这取决于nums[i]和nums[i]+f(i - 1)的大小关系。以[-2,1,-3,4,-1,2,1,-5,4]为例子,max表示f(i - 1)为以下标i-1结尾。输出:[0,1,0,1]

2024-04-19 10:19:49 1044

原创 二维数组之前缀和中篇

此时map中有(0, 1),(3, 1),(7, 1),(14, 2),(16, 1),(13,1),(18, 1),(20,1)。pre += nums[6],等于18,18 - 7等于11,不在map中,此时map中有(0, 1),(3, 1),(7, 1),(14, 2),(16, 1),(13,1),(18, 1)。pre += nums[4],等于13,13 - 7等于6,不在map中,此时map中有(0, 1),(3, 1),(7, 1),(14, 1),(16, 1),(13,1)。

2024-04-18 10:02:30 1230

原创 回文串中篇

看这篇文章之前,可以先看看。这次再分享三个关于回文串的题。

2024-04-17 10:21:44 1988 1

原创 回文串首篇

同时题目要求忽略大小写,这里只有数字和字母才有可能进入第二个else if,值得注意的是,toUpperCase方法在遇到大写字母或者数字,就是其本身,遇到小写字母将其转换为大写字母。这题的基本思路因为题目说只能删除一次,于是头尾指针在移动过程中,如果出现不同字符的情况,就有两种可能,要么删除头指针指向的字符,要么删除尾指针指向的字符,接着判断字符串是否回文,这里并没有真正删除,而是将指针移动一次。输入: s = “A man, a plan, a canal: Panama”输入: s = “aba”

2024-04-16 09:34:34 610

原创 二维数组之二维前缀和首篇

先给出一个示例,在给出计算二维矩阵二维前缀和的公式。要求f(2,2)前缀和,需要求f(1,2)、f(2,1)以及f(1,1)的前缀和,显然f(1,2)和f(2,1)会加上两次f(1,1),所以需要减去一次f(1,1)最后加上矩阵martix[2][2]的值。求二维矩阵前缀和代码如下。前两个for循环是将左侧和上侧进行初始化。

2024-04-15 10:54:42 483 1

原创 二叉树之遍历

之前有说到二叉树的建树,这次讲讲二叉树的遍历过程。int val;本文将用示例来详细描述二叉树深度优先遍历中后序遍历以及层序遍历的详细过程,而二叉树的前序遍历和中序遍历与前序遍历类似,就不再展开阐述。示例如下图所示。

2024-04-14 10:26:23 1104 1

原创 Java多线程同步

多线程总是异步执行,但是在某些情况下,一个线程需要等待另一个线程执行完成后才能执行,这就是线程的同步。在Java中有多种API可以实现线程的同步,接下来就介绍几种线程同步方式。

2024-04-13 21:23:10 440

原创 二叉树之建树

树结构如下所示。二叉树的建树逻辑一般可以采用后序遍历的逻辑,先创建父结点,然后通过递归的方式得到左右孩子结点,最后将父节点返回。

2024-04-12 19:34:23 1039

原创 排序之快速排序

sort方法结束,返回元素4所在的下标,经过一次sort方法,得到了左侧小于4的序列,和右侧大于4的序列。sort方法结束,返回5所在下标,5左侧[],右侧[6],继续递归merge方法,左侧因为l>r(l为5的下标,r为6的下标,返回5的下标,进入mergel和r分别传入5的下标,和5的下标-1,l肯定大于r),右侧因为l==r(l为5的下标,r为6的下标,返回5的下标,进入mergel和r分别传入5的下标+1,和6的下标,l等于r),而导致递归停止。走到if判断,i < j,显然i=j不满足条件。

2024-04-11 15:53:11 891 3

原创 排序之堆排序

注意堆调整是自顶向下的,此时tmp将元素2的值进行保存,第一个if比较左右两个子节点,左节点7大于右节点5,不满足条件,进入第二个if,左节点7大于父节点2,替换根节点的值为7,之后i指向左节点7,之后遍历左节点7的右节点6,第一个if,6>4,不满足条件,进入第二个if,此时nums[k]为6,tmp为2,i指向了结点7的位置,6>2,则将nums[i] = nums[k],将7的值修改为6,i指向左节点6。该数组长度为7,7/2-1为2,下标2对应位置为8,为最后一个非叶子结点。

2024-04-10 10:35:38 2419 1

原创 排序之归并排序

再看一个例子,[8, 12, 1,5],l指向8,r指向mid+1,为1,此时,比较8和1的大小,1小,tmp数组第一个元素赋值为1,r++,指向5,比较8和5的大小,5小,将tmp数组的第二个元素赋值为5,r++,r大于right,跳出第一个while循环,第二个while循环,判断l是否小于mid,显然l指向为8,小于mid,将tmp中第三个元素和第四个元素赋值为8和12,跳出第二个while循环,此时r大于right,不会进入第三个while循环。将排好序的tmp数组,赋值给nums数组。

2024-04-09 10:22:51 712

原创 Java中的双冒号

下面来具体看个lambda方法体中调用静态方法的例子。再看一个lambda方法体中调用构造方法的例子。

2024-04-08 10:14:38 422

原创 Java中的泛型

list声明了Integer,而list2声明了String,但是本质上是同一类,即ArrayList,的输出结果为true。

2024-04-07 16:36:27 770

空空如也

空空如也

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

TA关注的人

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