04 2023 档案
摘要:题目链接:1031. 两个非重叠子数组的最大和 方法:前缀和 + 哈兮 解题思路 考虑暴力解法,枚举以 $i$ 结尾的长度为 $firstLen$ 的子数组,求 $[i + 1, n - 1]$ 中长度为 $secondLen$ 长度的子数组和的最大值,最后取两者和的最大值; 优化:前缀和 + 哈兮
阅读全文
摘要:题目链接:剑指 Offer II 017. 含有所有字符的最短字符串 方法:同向双指针 解题思路 基本思路:统计 $t$ 字符串中每个字符的个数,然后使用双指针遍历字符串 $s$,当窗口覆盖 $t$ 中所有字符时,开始缩短左指针到可以到达的最右侧,取窗口最小的字符串为答案; 需要考虑的问题: 什么情
阅读全文
摘要:题目链接:1163. 按字典序排在最后的子串 方法:双指针 解题思路 【正常走路我不走,就是跳,就是玩】 任何非后缀子串字典序都小于其相应的后缀子串,如 $s[i, i + k] < s[i, n - 1]$, $k < n - 1$,故答案一定为后缀子串,即 $s[i, n - 1]$; 观察数据
阅读全文
摘要:题目链接:1105. 填充书架 方法一:记忆化搜索 解题思路 $dfs(i)$:从 $i$ 到 $n - 1$ 书放置的最小高度总和; 对于每一层:枚举当前层放置从 $i$ 开始的书,放置几本时整体的高度最优,按题目要求,必须是从 $i$ 开始的连续几本书,当前层的高度取最优方案中书的最高值; 返回
阅读全文
摘要:题目链接:6392. 使数组所有元素变成 1 的最少操作次数 方法一:计算最短的gcd为1的子数组 解题思路 本题目标:使得所有的数组元素都变为 $1$,通过求相邻元素 $gcd$ 将其赋值给一方的方式; 思路: 若想操作数最少,那么就是不为 $1$ 的数 $x$ 和 1 求 $gcd$,即 $x
阅读全文
摘要:题目链接:6390. 滑动子数组的美丽值 方法:计数排序 解题思路 维护窗口内的每个数字出现的次数,然后从小到达遍历哈希计数数组,统计遍历过的总次数 $cnt$,当 $cnt$ >= $x$ 时,说明当前的哈希数组下标即为当前窗口的第 $x$ 小的数。 代码 class Solution { pub
阅读全文
摘要:题目链接:剑指 Offer II 009. 乘积小于 K 的子数组 方法:同向双指针 解题思路 当 $[l, r]$ 子数组的乘积等于 $k$ 时,表明以 $l$ 为左端点且乘积为 $k$ 的子数组的数量为 $r - l + 1$,随着数组长度增加乘积一定增大($[l, r]$ 已经包含端点为 $1
阅读全文
摘要:题目链接:剑指 Offer II 005. 单词长度的最大乘积 方法:转化为二进制位 + 位运算 解题思路 将 $words[i]$ 字符串中包含的字母转换为二进制位上的 $1$,字符 'a' 对应二进制中的第 $0$ 位上的 $1$,这样每个字符串就对应一个二进制数。 通过两个字符串的二进制数进行
阅读全文
摘要:一、注册 在添加 $disassembler$ 时,在 llvm/lib/Target/XXX/Disassembler/XXXDisassembler.cpp 中会通过 $RegisterMCDisassembler()$ 将该 $pass$ 进行注册。 二、调用 (1)在 $XXXDisasse
阅读全文
摘要:题目链接:235. 二叉搜索树的最近公共祖先 方法:利用二叉搜索树性质 解题思路 若两个节点值都大于或小于当前节点,那么其 $LCA$ 一定在左右子树中,否则即为当前节点。 代码 class Solution { public: TreeNode* lowestCommonAncestor(Tree
阅读全文
摘要:题目链接:36. 二叉树的最近公共祖先 方法:回溯 解题思路 若两个节点 $p$,$q$ 分别出现在节点 $x$ 的左右子树中,那么该节点就是 $LCA(p, q)$,并且只可能出现在节点 $x$ 的左右子树中 。 代码 class Solution { public: TreeNode* lowe
阅读全文
摘要:题目链接:剑指 Offer 45. 把数组排成最小的数 方法:排序 解题思路 将数字转化为字符串数组,然后 $sort()$; cmp()函数 static bool cmp(string a, string b) { return a + b < b + a; } 代码 // 写法一 class
阅读全文
摘要:题目链接:1125. 最小的必要团队 方法:状态压缩 + 0,1背包 解题思路 状态压缩:由题目可知,$req_skills$ 存放的是所有技能的集合,每个人会其中的某几项。若将 $req_skills$ 中的每个技能对应二进制上的一位 $1$,可以得到一个标志 $target$,那么每个人也将得到
阅读全文
摘要:题目链接:[2646. 最小化旅行的价格总和](https://leetcode.cn/problems/minimize-the-total-price-of-the-trips/) ## 方法一:dfs + 树形dp ### 解题思路 - 先不考虑哪些节点的代价需要减半: - 由题可知,本题的数
阅读全文
摘要:题目链接:337. 打家劫舍 III 方法:树形dp 解题思路 对于每个节点,可能有选或者不选两种情况,对于两种情况下的数值均进行返回,其可以有子节点的数值转移而来; 假设第一个返回值表示选当前节点的值 $select$,第二个表示不选的值 $no$_$select$,先计算其子节点的返回值,$le
阅读全文
摘要:题目链接:剑指 Offer II 085. 生成匹配的括号 方法:递归 解题思路 通过选择当前加 '(' 或 ')',递归的计算所有答案。 注意:对于 ')' 的选择,只有当前 ')' 数量少于 '(' 时才可以选择; 代码 class Solution { public: vector<strin
阅读全文
摘要:题目链接:剑指 Offer 65. 不用加减乘除做加法 方法:二进制运算 解题思路 对于两个数 $a$ 和 $b$,其无进位的二进制位的和为 no_c = a ^ b,有进位的二进制位的和为 c = a & b << 1;有 a + b = no_c + c; 但是由于不能使用加法,那么继续对 no
阅读全文
摘要:题目链接:2642. 设计可以求最短路径的图类 方法一:Dijkstra 解题思路 每次调用 $shortestPath(st, ed)$ 时,就通过 $Dijkstra$ 算法计算 $st$ -> $ed$ 的最短路。 代码 朴素写法 class Graph { private: vector<v
阅读全文
摘要:题目链接:1040. 移动石子直到连续 II 方法:找规律 解题思路 参考—【图解】下跳棋 代码 class Solution { public: vector<int> numMovesStonesII(vector<int>& stones) { sort(stones.begin(), sto
阅读全文
摘要:题目链接:剑指 Offer 64. 求1+2+…+n 方法:逻辑运算符短路原则 解题思路 例如:对于表达式 $A && B$,若 $A$ 为 $false$,那么就不会计算 $B$; 代码 class Solution { public: int sumNums(int n) { n && (n +
阅读全文
摘要:题目链接:1023. 驼峰式匹配 方法:双指针 解题思路 对于当前询问 $query$ 和 模式串 $pattern$,初始化两个指针分别指向起始位置。 若两个字符相同则都右移一位;否则判断当前 $query$ 对应的字符是否为大写字母,若是则返回 $false$,否则其指针右移一位;若有一个指针到
阅读全文
摘要:题目链接:1042. 不邻接植花 方法:位运算 解题思路 根据题目可知,一个花园最多有 $3$ 条边,因此每个花园一定可以有一个合适的种类,只需要与其邻接点的种类都不同即可,假设花的种类分别对应二进制位的第 $1$、$2$、$3$、$4$位(从低->高位),现在对于花园 $u$,计算其所有邻接点花园
阅读全文
摘要:题目链接:剑指 Offer 60. n个骰子的点数 方法:动态规划 解题思路 $n = 1$ 时可能的和为 $[1, 6]$,其概率为 $dp[1][] = [1/6, 1/6, 1/6, 1/6, 1/6, 1/6]$ $n = 2$ 时对于第一个骰子为 $1$ 时,第二个骰子可以为 $[1, 6
阅读全文
摘要:题目链接:剑指 Offer 62. 圆圈中最后剩下的数字 方法:约瑟夫环 + 倒推 解题思路 假设我们最好剩余的数字是 $N$。 执行完 "删除第三个元素" 的操作后,$N$ 在新数组中的位置 $P$ 的意义是什么?它表示,在新数组中,$N$ 前面有还有 $P$ 个元素。那么,在当前数组中,$N$
阅读全文
摘要:题目链接:剑指 Offer 59 - I. 滑动窗口的最大值 方法一:栈模拟队列 解题思路 模拟滑动窗口的移动过程,对于每个滑动窗口快速获取其最大值,通过栈模拟队列,可以在 $O(1)$ 时间复杂度获取最大值。 栈类: 属性:数组存储元素,栈顶但前指针,指向当前最大值的指针,指向前一个最大值的指针数
阅读全文
摘要:题目链接:1000. 合并石头的最低成本 方法:区间dp 解题思路 状态表示:$f[i][j]$ 集合:表示将 $[i, j]$ 的石堆合并成一堆的所有合并方式; 属性:集合中合并的所有代价总的最小值。 状态计算: 集合划分:将其分为 $[i, m]$ 和 $[m + 1, j]$,$m = i +
阅读全文
摘要:题目链接:1147. 段式回文 方法:贪心 解题思路 若左右较长的字符段能相同,那么将其分为较小的字符段也能相同,因此在最开始判断时,就要遵循原则:能拆尽拆,将其拆为最多字符段的情况。 代码 class Solution { public: int longestDecomposition(stri
阅读全文
摘要:题目链接:300. 最长递增子序列 方法:动态规划 解题思路 状态表示:$dp[]$ 集合:表示以 $i$ 结尾的所有递增子序列; 属性:$dp[i]$ 表示集合中最长子序列的长度。 状态计算: 集合划分:枚举以 $i$ 结尾的所有递增子序列的其前一个元素可能的下标 [0, i - 1],将其划分为
阅读全文
摘要:题目链接:1041. 困于环中的机器人 方法:模拟 解题思路 模拟机器人的行动过程,若再重复四轮之后仍没有回到起始状态,则机器人可以离开,否则不能离开。 代码 class Solution { public: bool isRobotBounded(string instructions) { in
阅读全文
摘要:题目链接:491. 递增子序列 方法:回溯 + 剪枝 解题思路 回溯:在每一个位置的时候判断当前元素是否可选,即是否大于等于前一个元素,满足条件时选取; 剪枝:由于本题目要求不能出现重复的子序列,也就是在回溯的每一层中选择的元素不能相同,因此可以在每一层设置一个平衡树,检测当前元素是否已经在该层的平
阅读全文
摘要:题目链接:1019. 链表中的下一个更大节点 方法:单调栈 解题思路 该类问题详解:单调栈解决 Next Greater Number 一类问题 代码 class Solution { public: vector<int> nextLargerNodes(ListNode* head) { vec
阅读全文
摘要:题目链接:2612. 最少翻转操作数 方法:BFS + AVLTree 解题思路 先不考虑被 $ban$ 的位置: 假设当前 $1$ 的位置在下标 $i$ 上,那么将其按照包含 $i$ 且长度为 $k$ 的数组反转一次所能得到的对应下标的可能结果是一个从 $i - k + 1$ 起始到 $i + k
阅读全文
摘要:题目链接:1017. 负二进制转换 方法一:进制转换 解题思路 除基取余法,当基数 $x$ 为负数时,注意将余数 $c$ 取绝对值。重复操作,$c = abs(n % x), n = (n - c) / x$,直到 $n = 0$。 代码 class Solution { public: strin
阅读全文
摘要:题目链接:1053. 交换一次的先前排列 方法:贪心 解题思路 为了保证字典序最大,应该尽可能的使得左侧的元素不变,首先考虑交换数组靠右侧的两个数字。 那么可以从右往左遍历,找第一个逆序对;若没有则返回原数组; 找到逆序对$(i, i + 1)$后,再对$j$从$i + 1$ ~ $n$遍历,找$a
阅读全文
摘要:题目链接:2608. 图中的最短环 方法:BFS + 技巧 解题思路 环一定包含$edges$数组中的某条边; 遍历$edges$数组,对于某一条边<$u, v$>,以$v$为起点进行$bfs$搜索,禁止通过边<$u, v$>(技巧)。在此种情况下若能搜到$v$,说明存在环,且当前环的长度为$当前层
阅读全文
摘要:题目链接:2607. 使子数组元素和相等 方法:分组 + gcd + 中位数 解题思路 题意:将$arr$中某个元素$+1$或$-1$,使得任意长度为$k$的子数组的元素总和相等,且总操作数最少; 1、首先考虑数组$arr$为非循环数组: 任意$k$长的子数组总和相等,则有下述情形,依次可以将$ar
阅读全文
摘要:题目链接:1039. 多边形三角剖分的最低得分 方法:区间dp 解题思路 区间 DP:最长回文子序列 最优三角剖分【基础算法精讲 22】 代码 回溯写法 class Solution { public: int minScoreTriangulation(vector<int>& values) {
阅读全文
摘要:题目链接:2611. 老鼠和奶酪 方法:贪心 解题思路 题目要求第$mouse1$恰好吃掉 $k$ 块奶酪的情况下,计算最大得分。 假设$mouse1$当前吃掉了下标为$i$处的奶酪,那么应该满足,$diff[i] = reward1[i] - reward2[i]$是当前所有$diff$值的最大值
阅读全文
摘要:题目链接:2610. 转换二维数组 方法:哈希表 解题思路 统计$nums$中每个元素的数量,然后每行输出其中的$1$个,直到元素全部输出。 代码 class Solution { public: vector<vector<int>> findMatrix(vector<int>& nums) {
阅读全文
摘要:题目链接:2609. 最长平衡子字符串 方法:模拟 解题思路 统计当前$0$和$1$的数量$cnt0$,$cnt1$,如果当前字符为'$0$',且$1$的数量不为$0$,说明$0$前面出现$1$,则重置$cnt0 = 1$,$cnt1 = 0$。每次计算当前的最大值。 代码 class Soluti
阅读全文
摘要:题目链接:2606. 找到最大开销的子字符串 方法:动态规划 解题思路 实际是:子数组最大和 初始化每个字母的价值,保存在vector<int> value(26)中; 设$dp[i]$表示以$s[i]$结尾的子字符串的最大开销,那么就可以使得dp[i + 1]和dp[i]联系起来,有两种情况: 将
阅读全文
摘要:题目链接:2605. 从两个数字数组里生成最小数字 方法:哈希 解题思路 本题有两种情况: 两个数组有共同元素,则取其中最小值返回; 两个数组没有共同元素,则取两个数组中各自的最小元素组成最小的两位数返回。 代码 class Solution { public: int minNumber(vect
阅读全文
摘要:题目链接:剑指 Offer 57 - II. 和为s的连续正数序列 方法一:同向双指针 解题思路 使用两个双指针维护一个窗口,设窗口中元素的和为$curSum$。当$curSum > target$时,左指针右移一位;当$curSum < target$时,右指针右移一位;当$curSum == t
阅读全文
摘要:题目链接:剑指 Offer 56 - II. 数组中数字出现的次数 II 方法一:位运算 解题思路 由题意知,其他数值都出现了三次,那么其数值二进制位上的$1$也至少出现了三次,那么我们可以统计数值每一位上$1$的个数的总和,然后遍历每一位上$1$的数量,若某一位上的$1$的数量不能被$3$整除,说
阅读全文
摘要:题目链接:剑指 Offer 56 - I. 数组中数字出现的次数 方法:位运算 + 分类 解题思路 异或运算:当两个相同的数异或时,结果为$0$; 对于本题,假设答案为$res1$ 和 $res2$,那么对数组中所有的数求异或时,其结果实际等于 $res1$ ^ $res2$;并且此结果中二进制位为
阅读全文
摘要:题目链接:72. 编辑距离 方法:回溯 / 动态规划 解题思路 参考:最长公共子序列 编辑距离【基础算法精讲 19】 代码 回溯写法 class Solution { public: int minDistance(string word1, string word2) { int n = word
阅读全文
摘要:题目链接:1092. 最短公共超序列 方法一:转换为lcs(最长公共子序列)问题进行求解 解题思路 先得到两个字符串$lcs$,然后再计算$ans$。 $lcs$的获取:最长公共子序列 编辑距离【基础算法精讲 19】 动态规划的$dp$数组在本题有两种实现方式 (1)vector<vector<st
阅读全文
摘要:题目链接:2603. 收集树中金币 方法:拓扑排序 解题思路 参考:拓扑排序 + 记录入队时间(Python/Java/C++/Go) 代码 class Solution { public: int collectTheCoins(vector<int>& coins, vector<vector<
阅读全文
摘要:题目链接:2601. 质数减法运算 方法:质数打表 + 二分 解题思路 每次将当前$nums[i]$减去一个质数(或不减),使得其变为为大于上一个数的最小值,可以给后面的元素更多减小的空间。 质数打表; 遍历数组$nums$,每次要和前一个数做比较,因此初始化前一个数为$last$。对于当前的$nu
阅读全文
摘要:题目链接:2602. 使数组元素全部相等的最少操作次数 方法:排序 + 前缀和 + 二分查找 解题思路 初始化$target = queries[i]$,根据题意,对于每次询问要将数组$nums$中的元素$=>target$,那么对于小于等于$target$的元素要加上一个数,而大于$target$
阅读全文
摘要:题目链接:剑指 Offer 49. 丑数 方法:动态规划 解题思路 参考:剑指 Offer 49. 丑数(动态规划,清晰图解) 代码 class Solution { public: int nthUglyNumber(int n) { int a = 0, b = 0, c = 0; int dp
阅读全文
摘要:题目链接:剑指 Offer 48. 最长不含重复字符的子字符串 方法:同向双指针 解题思路 初始化l = 0, r = 0; 右指针右移,直到[l, r]之间出现重复字符,然后将左指针右移,直到[l, r]之间没有重复字符; 即保证[l, r]窗口无重复字符,然后计算最大的窗口长度。 代码 clas
阅读全文
摘要:题目链接:剑指 Offer 46. 把数字翻译成字符串 方法:回溯、动态规划 解题思路 动态规划是回溯中“归”的过程; 思考回溯: (1)将$num$转换为字符串$s$; (2)对于当前位置$i$,可能有两种操作,将$s[i] => 字符$ 或 将$s[i, i + 1] => 字符$,即$dfs(
阅读全文
摘要:题目链接:1574. 删除最短的子数组使剩余数组有序 方法:双指针 + 找规律 解题思路 去除子数组的可能情况: 将第一个递减序列的左端点到末尾的子数组去掉; 将最后一个递减序列的右端点到起点的子数组去掉; 左端点:起点 和 第一个递减序列的左端点之间取, 右端点:最后一个递减序列的右端点和末尾之间
阅读全文
摘要:题目链接:1032. 字符流 方法:字典树 解题思路 理解题意:每一次查询是对从最开始到当前的字符组成的字符串$str$查询$words$数组中是否有字符串是$str$的后缀; 对于字符串的查找使用字典树,每次查询的时间复杂度为$O(L),L = max{word.length()}$,大大降低查找
阅读全文
摘要:题目链接:剑指 Offer 52. 两个链表的第一个公共节点 方法一:两次遍历 解题思路 将两个单链表的遍历指针先置于同一起跑线(相对于相交的点),然后会同时遍历到相交的节点。 注意:模拟下方代码即可理解,第一次遍历长度为长的链表长度,第二次遍历长度为短的链表长度。 代码 class Solutio
阅读全文
摘要:题目链接:剑指 Offer 44. 数字序列中某一位的数字 方法:找规律 解题思路 找第$n$位对应的数为几位数; 找该数的具体值; 找第$n$位在该数中的第几位。 {:style="width:500px"} 代码 class Solution { public: int findNthDigit
阅读全文
摘要:题目链接:剑指 Offer 42. 连续子数组的最大和 方法:动态规划 解题思路 参考动态规划详细解析——剑指 Offer 42. 连续子数组的最大和 注意: 很多同学首先会想到同向双指针,实际上本题由于$nums$数组的某一个元素的下一个元素可正可负,导致同向双指针要求的单调性无法满足; 使用$d
阅读全文
摘要:题目链接:剑指 Offer 41. 数据流中的中位数 方法一:插入排序 解题思路 每次添加一个数字时,通过插入排序添加,需要返回中位数时,根据元素个数进行返回。 代码 class MedianFinder { private: vector<int> nums; public: /** initia
阅读全文
摘要:题目链接:1626. 无矛盾的最佳球队 方法一:子集型回溯 + 记忆化 解题思路 先对$scores$和$ages$数组进行预处理得到$pair<int, int> a[n]$数组,$a[i].first = score[i], a[i].second = ages[i]$,然后进行$sort$排序
阅读全文
摘要:题目链接:剑指 Offer 40. 最小的k个数 方法:排序 解题思路 基于比较的排序,最低时间复杂度为$O(nlogn)$,空间复杂度为$O(1)$; 哈希计数,时间复杂度为$O(n)$,但需要额外的空间。 代码 // 基于比较的排序 class Solution { public: vector
阅读全文
摘要:题目链接:剑指 Offer 37. 序列化二叉树 取巧做法 class Codec { private: TreeNode* root; public: // Encodes a tree to a single string. string serialize(TreeNode* root) {
阅读全文
摘要:题目链接:1012. 至少有 1 位重复的数字 方法:数位dp 解题思路 参考:数位 DP 通用模板,附题单(Python/Java/C++/Go) 注意:其中$isNum$是用来针对前导$0$可能影响结果而设置的标志,如$010$(即$10$)实际是没有重复的数字,而由于前导$0$的影响使得是有重
阅读全文
摘要:题目链接:剑指 Offer 36. 二叉搜索树与双向链表 方法一:回溯 解题思路 {:width=1000} 代码 class Solution { private: int mx = INT_MIN, mi = INT_MAX; Node* start = NULL, * end = NULL;
阅读全文
摘要:题目链接:1625. 执行操作后字典序最小的字符串 方法:bfs暴力搜索 解题思路 初始化队列$q$,若$q$不为空,取队首字符串和$ans$进行比较,取其中字典序小的字符串,然后队首字符串对于两种操作可以生成两个字符串,将其中未出现过(即未遍历过)的字符串加入$q$中,继续循环,直到队列为空,返回
阅读全文
摘要:题目链接:1616. 分割两个字符串得到回文串 方法:模拟 + 双指针 解题思路 题目要求,找一个合适的下标 $idx$ 将 $a$ 分割为 $a[0, idx]$ 和 $a[idx + 1, n - 1]$,同样的 $b$ 分割为 $b[0, idx]$ 和 $b[idx + 1, n - 1]$
阅读全文
摘要:题目链接:2389. 和有限的最长子序列 方法:前缀和 + 二分查找 解题思路 根据题意,子序列与$nums$数组的元素顺序无关,因此可以先对$nums$从小到大排序,并计算前缀和$nums[i] += nums[i - 1]$,此时的$nums[i]$表示原来nums数组$[0, i]$的区间和。
阅读全文
摘要:题目链接:剑指 Offer 33. 二叉搜索树的后序遍历序列 方法:分治 解题思路 首先假设该序列能够构成某个二叉搜索树的后序遍历序列,那么这个序列会被分成3个部分:左子树序列,右子树序列,父节点,其中左右子树节点数可能为0; 现在就可以检查该序列是否符合这个规律,然后递归的判断子树是否符合规律。
阅读全文
摘要:题目链接:2488. 统计中位数为 K 的子数组 方法:前缀和 + 哈希 解题思路 根据题意可知,在$k$是中位数的子数组中,比$k$大的数 $-$ 比$k$小的数 $=$ $0$ || $1$。那么将两种状态,小于$k$置$-1$,大于$k$置$+1$,计算数组的前缀和$s$。 由于子数组要包含$
阅读全文
摘要:题目链接:1615. 最大网络秩 方法:暴力求解 解题思路 初始化每个节点邻接点的数量以及用矩阵保存边的信息,暴力枚举节点对,取其中秩的最大值。 代码 class Solution { public: int maximalNetworkRank(int n, vector<vector<int>>
阅读全文
摘要:题目链接:1223. 掷骰子模拟 方法:回溯 + 记忆化搜索 解题思路 回溯要点 参数列表 根据题目中的操作确定在递归中需要用到的上一层的某个变量或性质。 递归边界 即递归的最底层,确定其返回值。 记忆化搜索 由于在递归中会重复计算某一状态的值,那么我们在第一次计算出来后将其保存在数组中,再下一次遇
阅读全文
摘要:题目链接:1605. 给定行和列的和求可行矩阵 方法:贪心 解题思路 参考:思路?一个动画秒懂!附优化写法(Python/Java/C++/Go) 代码 class Solution { public: vector<vector<int>> restoreMatrix(vector<int>& r
阅读全文
摘要:题目链接:1617. 统计子树中城市之间最大距离 方法:子集型回溯 + 判断连通 + 树的直径 解题思路 枚举所有可能的子树 参考:子集型回溯 判断当前的子树是否合法,即当前树是否连通,通过$dfs$从某一个节点开始遍历子树,若遍历节点数量不等于子树节点数量,则不连通; 计算以每一个子树节点为起点能
阅读全文
摘要:题目链接:剑指 Offer 51. 数组中的逆序对 方法一:归并排序 解题思路 逆序对:即后面的数大于前面的数; 归并排序: 先分,在此过程中会先递归的将序列分为一段一段序列,并且每段序列之间的先后顺序是不变的。 再治,也即归并,归并的过程中会将两段序列进行比较$(A,B,B在A的后面)$,当出现$
阅读全文
摘要:题目链接:面试题 17.05. 字母与数字 方法:TwoSum 解题思路 (1)将字符量化为 $+1$,数字量化为 $-1$,那么当子数组的和$subSum = 0$时,表示子数组中的字符和数字的数量相等; (2)$subSum = s[j] - s[i],j >= i,i = 1, 2, ...$
阅读全文
摘要:题目链接:108. 将有序数组转换为二叉搜索树 方法:递归建树 解题思路 每次选取中间的元素作为根节点,递归创建左右子树,就可以保证左右子树的高度差绝对值不超过1 代码 /** * Definition for a binary tree node. * struct TreeNode { * in
阅读全文
摘要:题目链接:1590. 使数组和能被 P 整除 方法:前缀和 + 哈希 解题思路 (1)要求$(sum - sunSum)$ % $p = 0$,即要求 $[sum - (s[j] - s[i])]$ % $p = 0$, 即 $sum$ % $p = (s[j] - s[i])$ % $p$,即 $
阅读全文
摘要:题目链接:1. 两数之和 方法:哈希 解题思路 通过哈希记录每个$nums[i]$的下标$i$,然后遍历$nums$,找$target - nums[i]$的下标。 代码 class Solution { public: vector<int> twoSum(vector<int>& nums, i
阅读全文
摘要:题目链接:剑指 Offer 20. 表示数值的字符串 方法:模拟 解题思路 根据题意模拟,详情见代码注释。 代码 class Solution { public: bool isDecimal(string s){ int first_symbol = s.find_first_of('.'); /
阅读全文
摘要:题目链接:2379. 得到 K 个黑块的最少涂色次数 方法一:前缀和 解题思路 通过前缀和计算任意子区间 $[i, i + k - 1]$ 中字母 $W$ 的数量,$ans = min([i, i + k - 1].count('W'), i = 0, 1, ...)。$ 代码 class Solu
阅读全文
摘要:题目链接:剑指 Offer 47. 礼物的最大价值 方法:动态规划 解题思路 $当前位置的最大价值 = max(上方格子的最大价值,左边格子的最大价值) + 当前位置的价值$,即局部最优可以推出全局最优,简单递推即可。 代码 class Solution { public: int maxValue
阅读全文
摘要:题目链接:1599. 经营摩天轮的最大利润 方法:模拟 解题思路 模拟全部游客都进行游玩,计算其中能赚取的最大利润值以及对应的次数。 代码 class Solution { public: int minOperationsMaxProfit(vector<int>& customers, int
阅读全文
摘要:题目链接:1653. 使字符串平衡的最少删除次数 方法:动态规划 解题思路 对于字符串$s$,设使得字符串$s[0, i]$平衡的最小删除次数为$dp[i]$。 若$s[0, n - 2]$为平衡字符串,当$s[n-1]==b$时,则$dp[n-1] = dp[n-2]$;当$s[n-1]==a$时
阅读全文
摘要:题目链接:1096. 花括号展开 II 方法:DFS由内向外展开 解题思路 ylb:[Python3/Java/C++/Go/TypeScript] 一题一解:递归(简洁代码) 代码 class Solution { private: set<string> s; void dfsBrace(str
阅读全文
摘要:题目链接:982. 按位与为零的三元组 方法一:枚举(超时) 解题思路 直接枚举$i, j, k$分别取$[0, n-1]$,判断$($$nums[i]$ & $nums[j]$ & $nums[k]$$)$ $==$ $0$。由于本题的数量级较大 $n = 1000$,$n^3 = 10^9$,会
阅读全文
摘要:题目链接:1487. 保证文件名唯一 方法:哈希表 解题思路 设文件名s对应的出现次数为$cnt[s]$,当前需要创建的文件夹名为$names[i]$,会有两种情况: 当前文件夹名为出现过,则$cnt[names[i]] = 1$; 当前文件名之前出现过,则更新其后缀名$(cnt[names[i]]
阅读全文
摘要:题目链接:面试题 05.02. 二进制数转字符串 方法:找规律 解题思路 (1)题目要求:将一个$0-1$之间的实数通过二进制进行表示,并通过字符串形式输出。 (2)由于二进制的小数只能表示$\frac{1}{2} \frac{1}{4} \frac{1}{8} ... \frac{1}{2^n}$
阅读全文
摘要:题目链接:剑指 Offer 19. 正则表达式匹配 方法:动态规划 解题思路 详情见:逐行详细讲解,由浅入深,dp和递归两种思路 代码 class Solution { public: bool isMatch(string s, string p) { int n = s.size(), m =
阅读全文
摘要:题目链接:2363. 合并相似的物品 方法一:归并 解题思路 先对两个整数数组进行$sort$排序,然后对两个数组进行归并操作。 代码 class Solution { public: vector<vector<int>> mergeSimilarItems(vector<vector<int>>
阅读全文
摘要:题目链接:1144. 递减元素使数组呈锯齿状 方法:找规律 + 模拟 解题思路 对于一个整数数组 $nums$,可以转换为题目中两种锯齿数组,对于两种情况的转换取最小值。 并且由于操作只能将一个元素减1,因此: 对于第1种情况,只用下标为奇数的元素需要减小到比两边最小值小1; 对于第2种情况,只用下
阅读全文
摘要:题目链接:2574. 左右元素和的差值 方法:前缀和 + 后缀和 解题思路 第一遍算出 $nums$ 数组前缀和,第二遍计算 $answer$ 数组。 代码 class Solution { public: vector<int> leftRigthDifference(vector<int>& n
阅读全文
摘要:题目链接:1255. 得分最高的单词集合 方法:暴力回溯 解题思路 观察可以发现,本题的数据量范围较小,使用暴力回溯不超过$2^1$$^4$次,需要注意的有,当选择一个单词时,必须保证当前提供的字符集合中剩余字符能够组成该单词$check()$,选择以后将字符集合中对应字符数量减少$destroy(
阅读全文
摘要:题目链接:[1247. 交换字符使得字符串相同] 方法:找规律 解题思路 由于只能两个字符串之间交换字符,单个字符串内不允许交换,因此如果只有一个字符对不相同,那么一定无法通过交换变为相同字符串,同理当不相同的字符对为奇数时,也无法通过交换变为相同字符。 当不相同的字符对数为偶数时,现在考虑以下几种
阅读全文
摘要:题目链接:1238. 循环码排列 方法:格雷码 解题思路 令 $N = 2^n-1$,将 $i = 0, ... , N,$ 分别转换为其对应的格雷码,用 $g$ 数组存储,即 $g[i]$ 表示 $i$ 对应的格雷码的十进制的值。由于题目中 $start$ 表示的是格雷码的十进制值,且返回的为格雷
阅读全文
摘要:题目链接:1140. 石子游戏 II 方法一:dfs(超时) 解题思路 题目要求$Alice$取得的石子数尽可能的多,那么就要使得$Bob$取得的石子尽可能的少,但是$Bob$也想要取得更多的石子,因此$Alice$在每次选取时,要使得在此种选取方法下,$Bob$能取的石子数最小。 现定义$dfs(
阅读全文
摘要:题目链接:1326. 灌溉花园的最少水龙头数目 方法:贪心 解题思路 每次到达端点l时,寻找在此处能够到达的最远右端点; 思路一: 先对每个水龙头能够覆盖的 $[l, r]$ 构成的数组 $rg$ 按照 $l$ 进行从小到大排序,然后遍历右端点 $r=[0, n]$,对于当前 $r$,在 $rg$
阅读全文
摘要:题目链接:1792. 最大平均通过率 方法:优先队列 解题思路 (1)为了使得平均通过率最大化,应使得所有班级的总通过率最大,那么 $extraStudents$ 学生应该使得某一个班级的通过率增加量最大,才添加到该班级中。因此可以使用优先队列,确定优先级,每次为 $q.top()$ 的班级添加学生
阅读全文
摘要:题目链接:15. 三数之和 方法:排序 + 相向双指针 解题思路 由题意可知,排序不影响结果,非递减排序之后3数之和满足单调性,即$x < x1$ || $y < y1$ || $z < z1$,$f(x, y, z) < f(x1, y1, z1)$; 现在枚举$x$下标$0 <= i <= n
阅读全文
摘要:题目链接:1237. 找出给定方程的正整数解 方法一:二分查找 解题思路 枚举 $x$,然后对 $y$ 进行二分查找,确定满足 $customfunction.f(x, y) == z$ 的数对 $(x, y)$,将其加入 $ans$ 中,最终返回 $ans$。 代码 /* * // This is
阅读全文
摘要:题目链接:1139. 最大的以 1 为边界的正方形 方法:二维数组前缀和 解题思路 假设以 $(i, j)$ 为左上角端点的正方形网格边长为 $d$,则该正方形的四条边 $up、down、left、right$ 均为$d$,两者为充分必要条件。根据二维前缀和运算可得: up = s[i][j + d
阅读全文
摘要:题目链接:1250. 检查「好数组」 方法:最大公约数gcd 裴蜀定理简介 (1)若 $a,b$ 是整数,且 $gcd(a,b)=d$,那么对于任意的整数 $x,y$,$ax + by$ 都一定是 $d$ 的倍数,特别地,一定存在整数 $x,y$,使 $ax+by=d$ 成立。 (2)推论:$a,b
阅读全文
摘要:题目链接:496. 下一个更大元素 I 方法一:模拟 + 哈希表 解题思路 通过哈希表存储,$nums$ 数组中元素对应的坐标,元素->坐标。 然后模拟查找过程。 代码 class Solution { public: vector<int> nextGreaterElement(vector<in
阅读全文
摘要:题目链接:1124. 表现良好的最长时间段 方法:前缀和 + 单调栈 前缀和简介 对于数组 $a[n]$,其前缀和数组 $s[n + 1]$, $s[i]$ 表示数组 $a[0, i - 1]$ 的和,$1 ≤ i ≤ n$。 s[0] = 0; for (int i = 1; i <= n; i
阅读全文
摘要:题目链接:1234. 替换子串得到平衡字符串 方法:同向双指针 解题思路 若可以通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」,则说明子串外任意字符的数量 $s ≤ n / 4$,否则一旦有一个字符的数量大于 $n / 4$,那么不论如何替换,必定有另一个字符的数量小于 $n /
阅读全文
摘要:题目链接:2563. 统计公平数对的数目 方法:排序 + 二分 解题思路 (1)先对数组进行排序,排序之后并不影响公平数对的数目; (2)对于任意一个 $j$,它的公平数对 $(i, j)$ 满足 $lower - nums[j] ≤ nums[i] ≤ upper - nums[j]$,即在 $[
阅读全文
摘要:题目链接:1138. 字母板上的路径 方法:模拟 解题思路 为了使得移动次数最小,每次移动方式为,"直角移动"(如下图),但由于 $z$ 字母位置的特殊性,当其作为目标字母和当前字母时,为了避免越界问题,需要调整 $x$ 和 $y$ 方向上移动的顺序。 {:width=400} 代码 class S
阅读全文
摘要:题目链接:1797. 设计一个验证系统 方法:哈希 解题思路 注意:在判断 $tokenId$ 是否出现过时,使用 $Time.count(tokenId)$,而不是使用 $Time[tokenId]$,因为只要使用之后,$tokenId$ 就会被添加进 $map$ 中,影响后续计数的结果。 代码
阅读全文
摘要:题目链接:1233. 删除子文件夹 方法一:排序 + 循环 解题思路 先对 $folder$ 数组根据字典序进行排序,排序完成后,扫描 $folder$ 数组。由于在同一个高层目录下的文件夹在同一段区域,那么这一段区域的第一个文件夹就是这一系列文件夹的最高层目录 $(high)$,将其加入结果数组中
阅读全文
摘要:题解链接:剑指 Offer 16. 数值的整数次方 方法一:迭代实现快速幂 解题思路 通过迭代的方法,自下向上实现快速幂求解过程,初始化结果 $res = 1$,底数 $t = x$ ,幂次为 $n$。当 $n$ 为奇数时,$res = res * t$,先乘上一个 $t$,此时还有 $n-1$ 个
阅读全文
摘要:题目链接:剑指 Offer 15. 二进制中1的个数 方法一:位运算 解题思路 x = n & -n,$x$ 表示 $n$ 的最后一位 $1$ 所对应的值,每减去一次 $x$,相当于有一个 $1$,$res ++$ 。 代码 class Solution { public: int hammingW
阅读全文
摘要:题目链接:1604. 警告一小时内使用相同员工卡大于等于三次的人 方法:模拟 解题思路 先对数据进行处理,根据 $name$ 将其时间存储在哈希表中,对哈兮表进行遍历,每个 $name$ 对应一个时间序列,首先对时间序列进行从小到大排序,从 $i = 2$ 开始遍历该序列,若存在 $list[i -
阅读全文
摘要:题目链接:11. 盛最多水的容器 方法:相向双指针 解题思路 根据题目要求,$2 <= n <= 10^5$,可知如果使用暴力求解,显然会超时。 使用双指针算法可以大大缩短时间复杂度,取 $[i, j]$ 双指针,初始化为 $i = 0, j = n - 1, i < j, $ 最大面积 $s =
阅读全文
摘要:题目链接:1210. 穿过迷宫的最少移动次数 参考:还在 if-else?一个循环处理六种移动! 代码 class Solution { private: static constexpr int mov[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; // 下
阅读全文
摘要:题目链接:1798. 你能构造出连续值的最大数目 方法:排序 + 贪心 解题思路 先将 $coins$ 数组从小到大排序,假设现有 $[0, x]$ 的连续整数序列,此时从 $coins$ 中选取一个值 $y$,则可以新构造 $[y, x + y]$ 序列;若 $x + 1 >= y$,则说明 $[
阅读全文
摘要:题目链接:剑指 Offer 14- II. 剪绳子 II 方法:数论 解题思路 将 $n$ 分为 $m$ 个数的和,使得这 $m$ 个数的乘积最大,那么应该将 $m$ 个数分为 $2$ 和 $3$ 的组合, 尽可能为 $3$。注意大数越界问题。 代码 class Solution { public:
阅读全文
摘要:题目链接: 剑指 Offer 14- I. 剪绳子 方法:数论 解题思路 将 $n$ 分为 $m$ 个数的和,使得这 $m$ 个数的乘积最大,那么应该将 $m$ 个数分为 $2$ 和 $3$ 的组合, 尽可能为 $3$。 代码 class Solution { public: int cutting
阅读全文
摘要:题目链接:1145. 二叉树着色游戏 方法:分类 解题思路 (1)$x$ 节点将二叉树分成了 $3$ 部分,分别是父节点子树、左子树、右子树(节点数分别为 n1 n2 n3); {:width=400} (2)为了使得二号玩家染色尽可能的多,应该让 $y$ 选择在 $x$ 相邻的节点。若存在以下一种
阅读全文
摘要:题目链接:129. 颜色交替的最短路径 方法:BFS 解题思路 当边的权重为 $1$ 时,可以使用 $BFS$ 计算最短路径; 因为起始边有两种情况,所以都需要计算,最后取两者的最小值; 代码 class Solution { public: vector<int> shortestAlternat
阅读全文
摘要:题目链接:剑指 Offer 12. 矩阵中的路径 方法:DFS 解题思路 根据 $word$ 中的第一个字母,从 $board$ 网格中开始查找,通过 $DFS$ 算法思想实现。 注意: 在每一轮开始查找前,每个位置的标记应该清除; 每一个位置有上 下 左 右四个方向可以选择; $DFS$ 查找进入
阅读全文