- 博客(30)
- 收藏
- 关注
原创 算法练习Day30 (Leetcode/Python-动态规划)
这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。
2024-01-17 17:54:05
1723
原创 算法练习Day29 (Leetcode/Python-动态规划)
Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。所以动态规划中每一个状态一定是由上一个状态推导出来的,,贪心没有状态推导,而是从局部直接选最优的,
2024-01-07 18:00:42
597
原创 算法练习Day28 (Leetcode/Python-贪心算法)
思路,此题求小于给定的数值N的最大的单调递增序列。对于每个数位,从后向前遍历,但凡发现前一位N[i-1]比后一位N[i]大,能做的就是把后一位N[i]置9,前一位置N[i-1]-1。
2024-01-05 16:02:50
636
原创 算法练习Day27 (Leetcode/Python-贪心算法)
若气球1是[2,5], 气球2是[3,6], 那么这个交集的区间是[3,5], 左边界是3,右边界是5,如果新来的气球的左边界大于了5,那么就无法用同一支箭射穿了。这种情况下,写法上可以选择更新原气球数组,每次都把当前气球i的左右边界更新为当前箭可射穿的左右边界,如果下一个气球i依然可以被同一支箭射穿,那就继续更新下一个气球的右边界,否则就不更新了,算是新一支箭的左右边界。因为排过序,新的左边界肯定大于旧的左边界,所以只要新的左边界小于旧的右边界,左边界就一定是落在原来区间的,反之则不然。
2024-01-02 09:52:57
1261
原创 算法练习Day25 (Leetcode/Python-贪心算法)
暴力解法O(n^2)的复杂度,做两次循环,遍历所有可能的子序列。可以从大饼干和胃口大的孩子开始遍历,本着不浪费的原则,大饼干优先满足大胃口的孩子,对于每一块饼干,将胃口从大到小的孩子和它一一对应,如果满足了一个孩子,则move to下一块次大的饼干。思路:分饼干,一个饼干最多分给一个人,若饼干大小>=孩子胃口则该孩子获得满足,设计算法尽可能满足更多的孩子。值,O(n)和O(n log n)可能相当接近。的增大,O(n log n)的增长速度将超过O(n)。
2023-12-30 08:46:08
1405
原创 算法练习Day24 (Leetcode/Python-回溯算法)
思路:分割一个字符串为四段,输出所有满足有效IP地址的分割。分为四段就是切三刀,判断每一段是不是有效,切完三刀后,看第四段是否符合要求,如果还是符合,就输出该结果,否则直接return。思路:列举所有可能的子集。那么所有的子集都是可以在backtrack中被放入result的,而不需要特别的判断了。因为是原数组内无元素重复,所以也不用担心子集重复。
2023-12-28 19:41:09
659
原创 算法练习Day23 (Leetcode/Python-回溯算法)
待取元素的candiate内无重复,区别于之前的组合问题,这里在横向遍历时for循环需要遍历所有元素,而不是在startIndex之后的元素(因为排列可以取[1,2,3],[1,3,2]这样的元素,组合的话就只能取[1,2,3],而无[1,3,2])。但是为了避免与纵向已经取过的元素在一个path里重复,要设置一个used元素记录之前path里已经取过的元素。其实只要每次横向遍历不用本次横向遍历里已经用过的元素就可以了。因为这个新元素最后可以取得的有效升序子序列之能是之前这个元素可以取得的有效子集。
2023-12-28 11:12:48
981
原创 算法练习Day22 (Leetcode/Python-回溯算法)
思路:从无元素重复的candidates中找和为target的组合,每一个组合中candidates中的元素可以被多次重复选取。是一个有效的选择,它可以在同一路径中多次被选择。(昨天那道题目里,元素不能被重复选取,所以传入的。本身),这意味着你不会在后续的递归中重新考虑之前已经处理过的元素。开始循环,算法仍然确保了不会生成重复的组合。这意味着在每一层递归中,都可以重新选择当前正在考虑的数字。这道题和昨天的非常类似,只不过昨天的不能重复选取。已经被考虑过,那么在后续的递归中就不会再生成。
2023-12-25 13:36:27
1030
原创 算法练习Day21 (Leetcode/Python-回溯算法)
这里一个数字对应三个字母,所以相当于二叉树变得更宽了(每一层有更多的子节点)。另外注意,这里用来记录每条“路径”的是string,所以不能用pop()来回溯,而要用[:-1]思路:和昨天的那题很相似,不过结束条件不太一样。以及在回溯的时候需要多记录一个值。
2023-12-24 18:50:47
1138
1
原创 算法练习Day19 (Leetcode/Python-二叉树)
一点碎碎念:写博客的初衷就是记录自己的练习的过程。所以这个博客里的大部分答案是源于其他博客的,主要是卡哥的代码随想录(link见reference),我只是答案的搬运工,不过我附上了主要是自己写的思路。写这个博客的目的是记录思路方便自己回看复习,也是站在一个刷题入门者的角度阐述一下自己的思路吧,如果能鼓励到其他刷题的同路人或者带来一点点的启发也算是额外之喜了。注意二叉树是有序的,根据例子,是进行了右中左的顺序累加的。思路:二叉搜索树上每个节点按序累加之前的节点值之和,成为更大的节点值。
2023-12-22 23:53:04
1185
原创 算法练习Day18 (Leetcode/Python-二叉树)
思路:这道题仅仅是要求以合理方式把一个值插入二叉树搜索树中,由于二叉搜索树是有排序的(右子树值>父节点值>左子树值),所以只要把这个值插入到叶节点下就是合理的,这样原有的tree的结构几乎不用调整。如果找到一个节点,发现p在其左子树,q在其右子树或者反之,该节点即是公共祖先。注意,有可能某节点并没有左或者右子树了,即该节点自己既是p或者q,又是待求的公共祖先。思路:删除binary search tree的一个节点比加入一个节点要难。因为如果被删除的节点左右子树都存在,那么就需要考虑补位问题。
2023-12-21 16:36:30
1092
原创 算法练习Day17 (Leetcode/Python-二叉树)
思路:BST 是一个有序的二叉树(左子树所有节点小于其父节点的值,右子树的所有节点的所有值则大雨其父节点的值。左右子树也分别是二叉树。),所以这道题就先按顺序遍历数组,然后两两相邻值相减,最小的差值就是要求的。思路:这题求树的最后一层的最左节点。注意仅仅通过递归求后续遍历的方式找到最左节点是不够的,还要满足在最后一层。所以要选深度最大的最左叶节点。
2023-12-20 15:00:40
500
1
原创 算法练习Day16 (Leetcode/Python-二叉树)
注意递归代码里是在input时就算好了当前路径(包含当前节点的子节点)的sum值,进入递归代码后先判断sum是否符合要求。如果不符合,跳出递归后把当前节点的子节点减去,然后再探索下一个子节点。即该节点无左右子节点,且是父节点的左节点。右子节点可能有它的左叶子节点,左子节点也可能有它的左叶子节点。遇到左叶子节点的时候,记下数值。通过递归法求左子树左叶子之和和右子树左叶子之和,相加起来就是整个树的左叶子之和。3)搜索其中一条符合条件的路径,就需要返回值,以便在遇到合适的路径时返回。递归法则是代码更为简洁。
2023-12-19 16:14:27
1140
1
原创 算法练习Day15 (Leetcode/Python-二叉树)
思路:这里用迭代法,记录从root到当前节点的路径path于path_st。当当前节点为叶节点后,将到该叶节点的这条路径push入path中。并在处理完stack中所有节点后,输出path。stack后进先出来实现DFS。思路: 判断二叉树是否平衡,也就是二叉树的任何节点的左右子树高度差值不能超过1。这和求子树高度的题目类似。使用递归法时,但凡有个节点的左右子树高度差超过1,就一直return -1了,也就是不满足balanced了。
2023-12-18 19:57:39
414
原创 算法练习Day13 (Leetcode/Python-二叉树)
算法和时间复杂度都为O(N)。因为每个节点都要被遍历到,所以时间是O(N)。队列在最坏的情况下,也就是完全二叉树,队列包含树的最后一层的节点时,达到队列长度的最大值,即至多(N/2)+1个节点,所以空间复杂度是O(N)。但有时树的宽度也可以较窄。按层从上到下从左到右输出二叉树的值。注意,输出格式每层为一个list。
2023-12-14 14:52:35
491
1
原创 算法练习Day12 (Leetcode/Python-二叉树)
如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。深度为k,有2^k-1个节点的二叉树。除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h从1开始),则该层包含 1~ 2^(h-1) 个节点。有数值,。又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
2023-12-13 17:31:36
403
原创 算法练习Day11 (Leetcode/Python-堆栈和队列)
思路:维护一个长度为当前window长度的单调队列,每次output这个单调队列里最大的值就是所求的值。第二种写法里,单调队列中维护的是元素的序号而不是值本身,这样在判断是否需要挪出单调队列中最左(最大)的元素时,用if i-d[0] >= k: d.popleft()即可,感觉更加优雅。因为 heapq.heappop(pri_que), heapq.heappush(pri_que, (freq, key)) 的复杂度是O(logk),最多有n个元素要被push,复杂度就为O(nlogk)了。
2023-12-12 18:03:59
1101
原创 算法练习Day10 (Leetcode/Python-堆栈和队列)
利用堆栈后进先出的顺序来验证是否符合正确的order。这道题乍看不难,但是我第一次return False有遗漏情况,即右括号有多余的情况。建议先列出来所有要return False的情况,这样写起来更有条理。其实就三种不匹配的情况:1. 左括号多余:已经遍历完,但是栈不为空。2. 顺序不匹配:栈不为空,但是新输入的元素不匹配栈里top的元素。3. 右括号多余:栈已经空了,但是还有右括号。
2023-12-10 19:26:24
973
1
原创 算法练习Day9 (Leetcode/Python-堆栈和队列)
思路:和上一题相反,这里用队列实现栈。借助队列popleft先入先出再append的“循环”特性,把最后入的值挪到队列最top,即最左,也就是stack的top。思路:用stack来实现queue。stack是后进先出,然如果有两个stack,第一个stack按照。进后出(这里的加粗的后是元素进入第一个stack里“后”的顺序),也就实现了队列,所谓负负得正。进先出的顺序把元素push进第二个stack中,元素的顺序就变成了。pop and top为O(n),其他为O(1)来实现栈(stack)。
2023-12-09 06:29:22
873
原创 算法练习Day8 (Leetcode/Python-字符串)
思路:这里用了brute force,最坏的情况是每次都配对都是到最后一个元素才发现不匹配,那么复杂度是O(mn)。这里for循环设置好range稍作early stop。这道题更高效的方法是KMP,KMP的核心思想在这道题里是每次从haystack的第i位开始和needle对照后,若失败,下一次验证不一定要从haystack的第i+1位开始对照,根据上一次的对照结果,跳过绝不可能匹配的位数,再开始对照。这块需要通过计算KMP中的next数组得出。但是今日时间有限,尚未完全掌握。
2023-12-08 15:49:18
428
原创 算法练习Day7 (Leetcode/Python-字符串)
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。其实很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。对于输入字符串 "a5b",函数应该将其转换为 "anumberb"输出:打印一个新的字符串,其中每个数字字符都被替换为了number。样例输入:a1b2c3。
2023-12-07 08:16:16
1079
原创 算法练习Day6 (Leetcode/Python-哈希表)
从左到右选定第一个元素,然后以这个元素右侧隔壁的元素为left,排序数组的最右为right指针。while right > left # right的值一定大于等于left的,因为在之后的if elif else中right和left有可能相等,所以这里是right>left,而不是>=。比起昨天的2sum,就是多了一重循环,把每两组array的number之和的所有可能视为2sum里的一个array,再直接套用2sum的解法。所以是在遍历左右指针的时候,跳过重复的。今天接下来的两道题都是需要去重的。
2023-12-06 10:02:48
1033
1
原创 算法练习Day5 (Leetcode/Python-哈希表)
哈希表在python中通常使用dictionary表示。以下是dict相关的一些常用指令.get()set可以用于存储无序且唯一的元素。在 Python 中,集合(Set)的实现主要有两种类型:基于哈希表的散列集合(set类型)和基于有序列表的集合(或者使用list的方式)。setsetsandt, returntrueifts, andfalseotherwiseAntrues思路:用dict来记录出现过的letter,dict的查询比数组更快。
2023-12-05 16:48:51
1096
原创 算法练习Day4 (Leetcode/Python-链表)
每次互换两个Nodes(比如node1和node2),其实涉及三个Node,node1, node2, node2.next(的地址)。如果两个链表最后有相同的部分,假设A是更长的链表,那么一定只可能是在index = len(A)-len(B)(对更长的链表记)之后的node。所以,先计算两个链表各自的长度,再算出index。但是迭代法就不设置dummy_head了,每组node1和node2互换后,node1才是继续接下一组的node,node1.next也才是每轮迭代的output。
2023-12-03 17:36:20
881
1
原创 算法练习Day3 (Leetcode/Python-链表)
以下写法中,当current.next 为None,current就是表尾的最后一个元素,且这个元素的值是否等于val在上一个while循环里就已经被判断过了,直接跳出循环即可。while循环里,current从无实际意义的虚拟表头开始,每次判断的都是current.next,即下一个元素的值。思路:所谓双指针就是记录当前Node cur和上一个Node pre,用temp记录当前Node的原本的下一个Node,然后把pre赋给当前Node的next,实现reverse。Solution 递归法。
2023-12-02 18:14:54
1084
原创 算法练习Day2 (Leetcode/Python-数组/双指针)
从左到右遍历每个元素,右指针记录这个数组的右边界,左指针则是左边界。思路概述:此题的变化是把f(x) = x*2 改成了更有一般性的f(x)=ax^2+bx+c。其实只要判断一下a>0 还是a
2023-11-30 18:48:19
494
1
原创 算法练习Day1 (Leetcode/Python)
数组特点在内存地址中连续,不能单独删除,只能覆盖。对于数组问题,注意是否有重复,是否有序。方法上可以考虑二分法、双指针法、暴力解法等。易错点是数组的边界范围,数组的index是从0开始。注意index的整数运算。
2023-11-29 19:01:38
519
2
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人