算法
天天501
须知少年凌云志,曾许人间第一流
展开
-
用两个栈实现队列
in 栈用来处理入栈(push)操作,out 栈用来处理出栈(pop)操作。一个元素进入 in 栈之后,出栈的顺序被反转。当元素要出栈时,需要先进入 out 栈,此时元素出栈顺序再一次被反转,因此出栈顺序就和最开始入栈顺序是相同的,先进入的元素先退出,这就是队列的顺序。用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。转载 2023-10-16 07:15:00 · 25 阅读 · 0 评论 -
二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。我们先来回顾一下中序遍历的过程:先遍历树的左子树,再遍历根节点,最后再遍历右子树。所以最左节点是中序遍历的第一个节点。① 如果一个节点的右子树不为空,那么该节点的下一个节点是右子树的最左节点;② 否则,向上找第一个左链接指向的树包含该节点的祖先节点。转载 2023-10-16 07:15:00 · 17 阅读 · 0 评论 -
重建二叉树
前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历的结果。然后分别对左右子树递归地求解。根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。转载 2023-10-16 07:15:00 · 14 阅读 · 0 评论 -
树中两个节点的最低公共祖先
在二叉查找树中,两个节点 p, q 的公共祖先 root 满足 root.val >= p.val && root.val <= q.val。在左右子树中查找是否存在 p 或者 q,如果 p 和 q 分别在两个子树中,那么就说明根节点就是最低公共祖先。转载 2023-10-16 07:00:00 · 18 阅读 · 0 评论 -
把字符串转换成整数
将一个字符串转换成一个整数,字符串不是一个合法的数值则返回 0,要求不能使用字符串转换整数的库函数。转载 2023-10-15 10:28:59 · 20 阅读 · 0 评论 -
构建乘积数组
给定一个数组 A[0, 1,…, n-1],请构建一个数组 B[0, 1,…, n-1],其中 B 中的元素 B[i]=A[0]*A[1]*…*A[i-1]*A[i+1]*…转载 2023-10-15 10:28:26 · 12 阅读 · 0 评论 -
不用加减乘除做加法
递归会终止的原因是 (a & b) << 1 最右边会多一个 0,那么继续递归,进位最右边的 0 会慢慢增多,最后进位会变为 0,递归终止。a ^ b 表示没有考虑进位的情况下两数的和,(a & b) << 1 就是进位。写一个函数,求两个整数之和,要求不得使用 +、-、*、/ 四则运算符号。转载 2023-10-15 10:27:52 · 16 阅读 · 0 评论 -
求 1+2+3+...+n
条件与 && 具有短路原则,即在第一个条件语句为 false 的情况下不会去执行第二个条件语句。利用这一特性,将递归的返回条件取非然后作为 && 的第一个条件语句,递归的主体转换为第二个条件语句,那么当递归的返回条件为 true 的情况下就不会执行递归的主体部分,递归返回。本题的递归返回条件为 n <= 0,取非后就是 n > 0;递归的主体部分为 sum += Sum_Solution(n - 1),转换为条件语句后就是 (sum += Sum_Solution(n - 1)) > 0。转载 2023-10-15 10:27:12 · 18 阅读 · 0 评论 -
股票的最大利润
使用贪心策略,假设第 i 轮进行卖出操作,买入操作价格应该在 i 之前并且价格最低。因此在遍历数组时记录当前最低的买入价格,并且尝试将每个位置都作为卖出价格,取收益最大的即可。可以有一次买入和一次卖出,买入必须在前。转载 2023-10-14 10:50:56 · 17 阅读 · 0 评论 -
圆圈中最后剩下的数
让小朋友们围成一个大圈。然后,随机指定一个数 m,让编号为 0 的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续 0…直到剩下最后一个小朋友,可以不用表演。约瑟夫环,圆圈长度为 n 的解可以看成长度为 n-1 的解再加上报数的长度 m。因为是圆圈,所以最后需要对 n 取余。转载 2023-10-14 10:50:25 · 17 阅读 · 0 评论 -
扑克牌顺子
五张牌,其中大小鬼为癞子,牌面为 0。判断这五张牌是否能组成顺子。转载 2023-10-14 10:49:47 · 20 阅读 · 0 评论 -
n 个骰子的点数
使用一个二维数组 dp 存储点数出现的次数,其中 dp[i][j] 表示前 i 个骰子产生点数 j 的次数。把 n 个骰子扔在地上,求点数和为 s 的概率。空间复杂度:O(N)转载 2023-10-14 10:49:22 · 23 阅读 · 0 评论 -
圆圈中最后剩下的数
让小朋友们围成一个大圈。然后,随机指定一个数 m,让编号为 0 的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续 0…直到剩下最后一个小朋友,可以不用表演。约瑟夫环,圆圈长度为 n 的解可以看成长度为 n-1 的解再加上报数的长度 m。因为是圆圈,所以最后需要对 n 取余。转载 2023-10-13 08:45:00 · 21 阅读 · 0 评论 -
扑克牌顺子
五张牌,其中大小鬼为癞子,牌面为 0。判断这五张牌是否能组成顺子。转载 2023-10-13 08:45:00 · 22 阅读 · 0 评论 -
n 个骰子的点数
使用一个二维数组 dp 存储点数出现的次数,其中 dp[i][j] 表示前 i 个骰子产生点数 j 的次数。把 n 个骰子扔在地上,求点数和为 s 的概率。空间复杂度:O(N)转载 2023-10-13 08:45:00 · 16 阅读 · 0 评论 -
从尾到头打印链表
要逆序打印链表 1->2->3(3,2,1),可以先逆序打印链表 2->3(3,2),最后再打印第一个节点 1。而链表 2->3 可以看成一个新的链表,要逆序打印该链表可以继续使用求解函数,也就是在求解函数中调用自己,这就是递归函数。为了能将一个节点插入头部,我们引入了一个叫头结点的辅助节点,该节点不存储值,只是为了方便进行插入操作。不要将头结点与第一个节点混起来,第一个节点是链表中第一个真正存储值的节点。头插法顾名思义是将节点插入到头部:在遍历原始链表时,将当前节点插入新链表的头部,使其成为第一个节点。转载 2023-10-13 08:45:00 · 17 阅读 · 0 评论 -
扑克牌顺子
五张牌,其中大小鬼为癞子,牌面为 0。判断这五张牌是否能组成顺子。转载 2023-10-12 09:00:00 · 26 阅读 · 0 评论 -
n 个骰子的点数
使用一个二维数组 dp 存储点数出现的次数,其中 dp[i][j] 表示前 i 个骰子产生点数 j 的次数。把 n 个骰子扔在地上,求点数和为 s 的概率。空间复杂度:O(N)转载 2023-10-12 09:00:00 · 17 阅读 · 0 评论 -
从尾到头打印链表
要逆序打印链表 1->2->3(3,2,1),可以先逆序打印链表 2->3(3,2),最后再打印第一个节点 1。而链表 2->3 可以看成一个新的链表,要逆序打印该链表可以继续使用求解函数,也就是在求解函数中调用自己,这就是递归函数。为了能将一个节点插入头部,我们引入了一个叫头结点的辅助节点,该节点不存储值,只是为了方便进行插入操作。不要将头结点与第一个节点混起来,第一个节点是链表中第一个真正存储值的节点。头插法顾名思义是将节点插入到头部:在遍历原始链表时,将当前节点插入新链表的头部,使其成为第一个节点。转载 2023-10-12 09:00:00 · 23 阅读 · 0 评论 -
n 个骰子的点数
使用一个二维数组 dp 存储点数出现的次数,其中 dp[i][j] 表示前 i 个骰子产生点数 j 的次数。把 n 个骰子扔在地上,求点数和为 s 的概率。空间复杂度:O(N)转载 2023-10-11 09:00:00 · 17 阅读 · 0 评论 -
从尾到头打印链表
要逆序打印链表 1->2->3(3,2,1),可以先逆序打印链表 2->3(3,2),最后再打印第一个节点 1。而链表 2->3 可以看成一个新的链表,要逆序打印该链表可以继续使用求解函数,也就是在求解函数中调用自己,这就是递归函数。为了能将一个节点插入头部,我们引入了一个叫头结点的辅助节点,该节点不存储值,只是为了方便进行插入操作。不要将头结点与第一个节点混起来,第一个节点是链表中第一个真正存储值的节点。头插法顾名思义是将节点插入到头部:在遍历原始链表时,将当前节点插入新链表的头部,使其成为第一个节点。转载 2023-10-11 09:00:00 · 17 阅读 · 0 评论 -
滑动窗口的最大值
例如,如果输入数组 {2, 3, 4, 2, 6, 2, 5, 1} 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,他们的最大值分别为 {4, 4, 6, 6, 6, 5}。假设窗口的大小为 M,数组的长度为 N。在窗口向右移动时,需要先在堆中删除离开窗口的元素,并将新到达的元素添加到堆中,这两个操作的时间复杂度都为 log。给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。维护一个大小为窗口大小的大顶堆,顶堆元素则为当前窗口的最大值。M),空间复杂度为 O(M)。转载 2023-10-11 09:00:00 · 13 阅读 · 0 评论 -
左旋转字符串
先将 “abc” 和 “XYZdef” 分别翻转,得到 “cbafedZYX”,然后再把整个字符串翻转得到 “XYZdefabc”。将字符串 S 从第 K 位置分隔成两个子字符串,并交换这两个子字符串的位置。转载 2023-10-11 09:00:00 · 13 阅读 · 0 评论 -
从尾到头打印链表
要逆序打印链表 1->2->3(3,2,1),可以先逆序打印链表 2->3(3,2),最后再打印第一个节点 1。而链表 2->3 可以看成一个新的链表,要逆序打印该链表可以继续使用求解函数,也就是在求解函数中调用自己,这就是递归函数。为了能将一个节点插入头部,我们引入了一个叫头结点的辅助节点,该节点不存储值,只是为了方便进行插入操作。不要将头结点与第一个节点混起来,第一个节点是链表中第一个真正存储值的节点。头插法顾名思义是将节点插入到头部:在遍历原始链表时,将当前节点插入新链表的头部,使其成为第一个节点。转载 2023-10-10 09:00:00 · 27 阅读 · 0 评论 -
滑动窗口的最大值
例如,如果输入数组 {2, 3, 4, 2, 6, 2, 5, 1} 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,他们的最大值分别为 {4, 4, 6, 6, 6, 5}。假设窗口的大小为 M,数组的长度为 N。在窗口向右移动时,需要先在堆中删除离开窗口的元素,并将新到达的元素添加到堆中,这两个操作的时间复杂度都为 log。给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。维护一个大小为窗口大小的大顶堆,顶堆元素则为当前窗口的最大值。M),空间复杂度为 O(M)。转载 2023-10-10 09:00:00 · 23 阅读 · 0 评论 -
左旋转字符串
先将 “abc” 和 “XYZdef” 分别翻转,得到 “cbafedZYX”,然后再把整个字符串翻转得到 “XYZdefabc”。将字符串 S 从第 K 位置分隔成两个子字符串,并交换这两个子字符串的位置。转载 2023-10-10 09:00:00 · 42 阅读 · 0 评论 -
翻转单词顺序列
题目应该有一个隐含条件,就是不能用额外的空间。虽然 Java 的题目输入参数为 String 类型,需要先创建一个字符数组使得空间复杂度为 O(N),但是正确的参数类型应该和原书一样,为字符数组,并且只能使用该字符数组的空间。任何使用了额外空间的解法在面试时都会大打折扣,包括递归解法。先翻转每个单词,再翻转整个字符串。转载 2023-10-10 09:00:00 · 17 阅读 · 0 评论 -
和为 S 的连续正数序列
输出所有和为 S 的连续正数序列。转载 2023-10-09 10:49:14 · 17 阅读 · 0 评论 -
和为 S 的两个数字
使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。在有序数组中找出两个数,使得和为给定的数 S。如果有多对数字的和等于 S,输出两个数的乘积最小的。转载 2023-10-09 10:48:43 · 17 阅读 · 0 评论 -
数组中只出现一次的数字
设不相等的两个元素分别为 z 和 k,遍历数组所有元素,判断元素与 diff 的异或结果是否为 0,如果是的话将元素与 z 进行异或并赋值给 z,否则与 k 进行异或并赋值给 k。而且这些相等的元素异或的结果为 0,因此最后 z 和 k 只是不相等的两个元素与 0 异或的结果,也就是不相等两个元素本身。对本题给的数组的所有元素执行异或操作,得到的是两个不存在重复的元素异或的结果。例如对于数组 [x,x,y,y,z,k],x。两个相等的元素异或的结果为 0,而 0 与任意数 x 异或的结果都为 x。转载 2023-10-09 10:48:07 · 18 阅读 · 0 评论 -
平衡二叉树
平衡二叉树左右子树高度差不超过 1。转载 2023-10-09 10:47:37 · 16 阅读 · 0 评论 -
二叉树的深度
从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。转载 2023-10-08 12:26:20 · 41 阅读 · 4 评论 -
二叉查找树的第 K 个结点
利用二叉查找树中序遍历有序的特点。转载 2023-10-08 12:25:37 · 31 阅读 · 1 评论 -
数字在排序数组中出现的次数
如果 h 的取值为 nums.length - 1,那么在查找最后一个位置时,binarySearch(nums, k + 1) - 1 = 1 - 1 = 0。这是因为 binarySearch 只会返回 [0, nums.length - 1] 范围的值,对于 binarySearch([2,2], 3) ,我们希望返回 3 插入 nums 中的位置,也就是数组最后一个位置再往后一个位置,即 nums.length。查找最后一个位置可以转换成寻找 k+1 的第一个位置,并再往前移动一个位置。转载 2023-10-08 12:25:05 · 57 阅读 · 0 评论 -
两个链表的第一个公共结点
当访问链表 A 的指针访问到链表尾部时,令它从链表 B 的头部重新开始访问链表 B;同样地,当访问链表 B 的指针访问到链表尾部时,令它从链表 A 的头部重新开始访问链表 A。这样就能控制访问 A 和 B 两个链表的指针能同时访问到交点。设 A 的长度为 a + c,B 的长度为 b + c,其中 c 为尾部公共部分长度,可知 a + c + b = b + c + a。转载 2023-10-08 12:24:29 · 17 阅读 · 0 评论 -
数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。转载 2023-10-07 15:13:53 · 65 阅读 · 0 评论 -
第一个只出现一次的字符位置
第一个只出现一次的字符位置。转载 2023-10-07 15:13:21 · 24 阅读 · 0 评论 -
算法题之替换空格
② 令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。P1 和 P2 从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容。因为一个空格要替换成三个字符(%20),所以当遍历到一个空格时,需要在尾部填充两个任意字符。③ 当 P2 遇到 P1 时(P2 <= P1),或者遍历结束(P1 < 0),退出。转载 2023-10-07 15:12:34 · 12 阅读 · 0 评论 -
算法题之丑数
把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,但 14 不是,因为它包含因子 7。习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 N 个丑数。转载 2023-10-07 15:12:01 · 16 阅读 · 0 评论 -
最长不含重复字符的子字符串
输入一个字符串(只包含 a~z 的字符),求其最长不含重复字符的子字符串的长度。例如对于 arabcacfr,最长不含重复字符的子字符串为 acfr,长度为 4。转载 2023-10-06 14:19:27 · 33 阅读 · 2 评论