笔记
Yuzuru Hanyu's pooh
幸得识卿桃花面,从此阡陌多暖春
展开
-
题解一百零二
剑指 Offer 51. 数组中的逆序对思路:归并排序归并排序就是把一个包含 n 个数的数组,折半拆分为两个子数组,然后再将这两个子数组再分,一直分下去,直到分为n个长度为1的元素。然后两两按大小归并。如此反复,直到最后形成包含 n 个数的一个有序数组。以示例1为例:归并排序的“分”过程整体“分”过程如下图所示:接下来执行在合并过程当中统计逆序对的数目(初始化逆序对的数目为0):class Solution { public int reversePairs(int[]原创 2020-08-02 13:34:09 · 121 阅读 · 0 评论 -
题解一百零一
剑指 Offer 35. 复杂链表的复制由题意可知,链表中每个节点可以用一个 [val, random_index] 表示:val:一个表示 Node.val 的整数。random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。链表的复制过程可分为两步:第一步是复制原始链表上的每个节点,并用next指针相连; 第二步是设置每个节点的random指针。—————————————————————————————————————思路:哈希表原创 2020-08-01 11:29:25 · 121 阅读 · 0 评论 -
题解一百
剑指 Offer 39. 数组中出现次数超过一半的数字思路:我们在遍历数组的时候记录两个值:1. 数组中的数字;2. 次数。使用一个计数count = 1,当前数res,每当数组中数和当前数res相同,那么count就加1,不相同就减一,因为是找出现的数超过数组的长度的一半,所以最后如果有出现的数超过数组长度一半的,count肯定是大于0的数。具体步骤:(1)当遍历到的数组当前数和res相等,即array[i] == res,则执行count加1;(2)若不相等,则count就减1;(3)如果c原创 2020-07-31 11:36:32 · 100 阅读 · 0 评论 -
题解九十九
剑指 Offer 61. 扑克牌中的顺子思路:数组中0可以当任何数用,所以当牌不连续的时候,它就可以替补,进而达到顺的要求。要判断五张牌是顺子应该满足以下条件:(1)除大王小王外,所有的牌无重复;(2)0的个数应该大于等于数组中两个连续数字之差。因为当数组中有俩连续的数之间差特别大,替补0的个数不够时,这就不是顺儿。算法过程:(1)对数组执行排序;(2)判别重复: 排序数组中的相同元素位置相邻,因此可通过遍历数组,判断 nums[i] = nums[i + 1]是否成立来判重,重复则直接返原创 2020-07-30 11:18:56 · 107 阅读 · 0 评论 -
题解九十八
剑指 Offer 58 - II. 左旋转字符串思路:一开始的思路是将字符串转化为字符串数组,在新建一个StringBuilder类型的变量 str保存字符。先遍历下标从n开始到字符数组尾部的字符添加到str中,再遍历字符数组前n个字符添加到str中。最后str转化为String类型返回。class Solution { public String reverseLeftWords(String s, int n) { char[] ch = s.toCharArray()原创 2020-07-29 10:57:10 · 88 阅读 · 0 评论 -
题解九十七
437. 路径总和 III原创 2020-07-28 13:13:26 · 84 阅读 · 0 评论 -
题解九十六
112. 路径总和思路:DFS记录已经经过的节点的值之和,每经过一个节点就减去这个节点的值,在叶子节点判断变量值是否为目标值。这样就可以把求解路径转换成从 root.left 或者 root.right 到叶子节点是否存在路径和为 sum - root.val 的路径:(1)若root为空,则返回false:(2)到达叶子节点时,递归终止,判断 sum 是否符合条件;(3)递归地判断root节点的左孩子和右孩子,并判断是否存在路径返回递归结果。class Solution { publ原创 2020-07-27 13:09:43 · 74 阅读 · 0 评论 -
题解九十五
剑指 Offer 67. 把字符串转换成整数写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应原创 2020-07-26 14:35:58 · 105 阅读 · 0 评论 -
题解九十四
剑指 Offer 36. 二叉搜索树与双向链表思路:由题可知,我们需要将二叉搜索树中序遍历使得它从小到大排列,中序遍历的顺序为“左—根—右”。我们设置链表的头节点head、前驱节点pre、当前节点cur,还有中序遍历函数dfs。∵需要将树构建成双向循环链表,∴相邻节点之间, pre.right = cur,cur.left = pre,且头节点head的前驱节点为尾节点,尾节点tail的后继节点为头节点,即head.left = tail 和 tail.right = head 。treeToD原创 2020-07-25 14:25:54 · 72 阅读 · 0 评论 -
题解九十三
450. 删除二叉搜索树中的节点给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。一般来说,删除节点可分为两个步骤:1、首先找到需要删除的节点;2、如果找到了,删除它。...原创 2020-07-24 13:11:49 · 65 阅读 · 0 评论 -
题解九十二
701. 二叉搜索树中的插入操作给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 保证原始二叉搜索树中不存在新值。注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。...原创 2020-07-23 11:09:55 · 68 阅读 · 0 评论 -
题解九十一
700. 二叉搜索树中的搜索原创 2020-07-22 10:42:06 · 72 阅读 · 0 评论 -
题解九十
100. 相同的树原创 2020-07-21 10:51:43 · 66 阅读 · 0 评论 -
题解八十九
剑指 Offer 26. 树的子结构思路:两层递归1、递归调用isSubStructure(A, B),先序遍历二叉树A;2、设置函数traverse,调用函数traverse( A, B),判断二叉树A中是否包含子树B。令二叉树A的根节点为节点A,二叉树B的根节点为B。若二叉树A为空或二叉树 B为空 时,直接返回 false;isSubStructure函数,返回值有三种情况:1、以节点 A 为根节点的子树包含树 B ,调用 traverse(A, B);2、当子树 B是 二叉树A的左原创 2020-07-20 11:02:26 · 126 阅读 · 0 评论 -
题解八十八
剑指 Offer 42. 连续子数组的最大和输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。示例1:输入: nums = [-2,1,-3,4,-1,2,1,-5,4]输出: 6解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。提示:1 <= arr.length <= 10^5-100 <= arr[i] <= 100(来源:力扣(LeetCode))思路:动态规划原创 2020-07-19 10:59:45 · 104 阅读 · 0 评论 -
题解八十七
剑指 Offer 58 - I. 翻转单词顺序思路:双指针(1)先使用trim()方法去掉字符串首尾的空白字符;(2)再设置双指针i,j,一开始两者都指向字符串尾部,倒序遍历字符串;(3)由指针i从后向前移动指针,每遍历完一个完整单词就将它加入StringBuilder类型的变量res;(4)指针i跳过两个单词之间的空格;(5)当指针i遍历到下一个单词的尾部时,令j = i;(6)循环执行步骤3—4,当i < 0时结束循环,并返回res.toString().trim()。例如:示原创 2020-07-18 12:06:39 · 106 阅读 · 0 评论 -
题解八十六
剑指 Offer 55 - II. 平衡二叉树限制:1 <= 树的结点个数 <= 10000思路:递归设置一个boolean全局变量balance,表示二叉树是否平衡。balance初始化为true,另外设置一个traverse函数来递归二叉树:(1)当root为空时,直接返回高度0;(2)递归得出左子树高度left和右子树高度right;(3)若左、右子树的高度差大于1,则balance = false;(4)返回当前子树的深度,即节点 root 的左 、 右子树的深度最大原创 2020-07-17 10:58:30 · 89 阅读 · 0 评论 -
题解八十五
剑指 Offer 55 - I. 二叉树的深度思路:递归因为求的是二叉树的深度,所以我们先求出左子树深度和右子树深度,再取两者中大的那个值:(1)如果root == null,直接返回0;(2)计算左子树深度,即递归调用maxDepth(root.left);(3)计算左子树深度,即递归调用maxDepth(root.right);(4)最后比较并返回较大的深度,并加1,因为根结点root的深度为0。class Solution { public int maxDepth(TreeN原创 2020-07-16 10:52:53 · 73 阅读 · 0 评论 -
题解八十四
剑指 Offer 54. 二叉搜索树的第k大节点给定一棵二叉搜索树,请找出其中第k大的节点思路:递归已知这个是一颗二叉搜索树,其特点是:1、左子树上所有节点的值均小于它的根节点的值;2、右子树上所有节点的值均大于它的根节点的值;3、左、右子树也分别为二叉搜树。我们可以使用中序遍历来遍历二叉树,其顺序一般是左—>中—>右。如果是左子树在前,右子树在后,遍历结果就是由小到大、如果是右子树在前,左子树在后,遍历结果就是由大到小因为我们要求的是第k大节点,所以我们只需要先遍历右子树,再原创 2020-07-15 13:01:51 · 142 阅读 · 0 评论 -
题解八十三
面试题68 - II. 二叉树的最近公共祖先说明:·所有节点的值都是唯一的。·p、q 为不同节点且均存在于给定的二叉树中。思路:递归根据题意可得,root、p、q一共有以下几种情况:1、p 和 q在分别 root 的分别在左、右子树中,则root就是公共祖先;2、p ,q都为root的左子节点,则返回lowestCommonAncestor(root.left,p,q);3、p,q都是root的右子节点,那么返回lowestCommonAncestor(root.right,p,q);递原创 2020-07-14 11:09:22 · 159 阅读 · 0 评论 -
题解八十二
面试题68 - I. 二叉搜索树的最近公共祖先说明:所有节点的值都是唯一的。p、q 为不同节点且均存在于给定的二叉搜索树中。思路:递归首先这是一颗二叉搜索树,且最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”题中给出了两个重要条件:1、所有节点的值都是唯一的。2、p、q 为不同节点且均存在于给定的二叉搜索树中。因此存在以下几种情况:(1)如果二叉树为空,则返原创 2020-07-13 12:57:27 · 77 阅读 · 0 评论 -
题解八十一
剑指 Offer 57 - II. 和为s的连续正数序列思路:滑动窗口我们利用滑动窗口来筛选正确答案。设置滑动窗口的左右边界分别为left、right。最开始的时候滑动窗口位于数组[1,2,3…n]的最左侧,且初始化 left = 1,right = 0:1、left初值必须为1,不能为0,否则有[0,1,2,3…]的非法答案;2、right初值为0,因为滑动窗口里的数字总和为sum +=right,要保证它能经过1;滑动窗口为闭区间[ left, right],窗口的左边界和右边界永远只能向原创 2020-07-12 11:07:16 · 235 阅读 · 0 评论 -
题解八十
剑指 Offer 50. 第一个只出现一次的字符在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。示例:s = “abaccdeff”返回 “b”s = “”返回 " "限制:0 <= s 的长度 <= 50000(来源:力扣(LeetCode))思路:哈希表遍历字符串 s ,使用哈希表统计 “各字符数量是否 >1 ”,再遍历字符串 s ,在哈希表中找到首个 “数量为 1的字符”,并返回。具体步骤:(1)当字符串s为空串,原创 2020-07-11 11:01:29 · 67 阅读 · 0 评论 -
题解七十九
剑指 Offer 11. 旋转数组的最小数字思路:二分查找因为原数组是一个排序数组,所以用二分查找比较适合。我们将数组分为左排序数组,和右排序数组,例如数组[3, 4, 5, 1, 2],[3, 4, 5]为左排序数组,[1, 2]为右排序数组,且旋转数组的最小元素即为寻找右排序数组的首个元素 numbers[x],所以numbers[3] = 1为旋转点。具体步骤:(1)设置两个指针left、right分别指向数组的左右两端,其中点mid = left + (right - left) /原创 2020-07-10 11:03:28 · 75 阅读 · 0 评论 -
题解七十八
35. 搜索插入位置思路:设置一个指针idx。遍历数组,当数组元素不等于target且小于target时,idx = idx + 1.最后返回idx即可。class Solution { public int searchInsert(int[] nums, int target) { if (nums.length == 0) return 0; int idx = 0; for (int i = 0; i < nums.length原创 2020-07-09 11:03:08 · 78 阅读 · 0 评论 -
题解七十七
剑指 Offer 22. 链表中倒数第k个节点输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。示例:给定一个链表: 1->2->3->4->5, 和 k = 2.返回链表 4->5.(来源:力扣(LeetCode))思路:因为题目求的是倒数k个结点,所以我们设置一个指针node,先原创 2020-07-08 10:54:54 · 63 阅读 · 0 评论 -
题解七十六
303. 区域和检索 - 数组不可变说明:1、你可以假设数组不可变。2、会多次调用 sumRange 方法。(来源:力扣(LeetCode))思路:使用前缀和方法进行预处理,即计算数组开头的若干连续元素的和。我们用res[k] 表示 nums 的前 k 个元素(即 nums[0…k))的元素之和,0 ≤ k ≤ n。如图所示,前缀和数组的定义中使用了左闭右开区间,这种表示方法的优点之一是很容易做区间的减法。由此可以得出,前缀和的计算公式为res[i + 1] = res[i] + nu原创 2020-07-07 11:28:53 · 63 阅读 · 0 评论 -
题解七十五
剑指 Offer 57. 和为s的两个数字输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。示例 1:输入:nums = [2,7,11,15], target = 9输出:[2,7] 或者 [7,2]示例 2:输入:nums = [10,26,30,31,47,60], target = 40输出:[10,30] 或者 [30,10]限制:1 <= nums.length <= 10^51 <=原创 2020-07-06 10:37:16 · 81 阅读 · 0 评论 -
题解七十四
剑指 Offer 52. 两个链表的第一个公共节点注意:如果两个链表没有交点,返回 null.在返回结果后,两个链表仍须保持原有的结构。可假定整个链表结构中没有循环。程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。(来源:力扣(LeetCode))思路:双指针使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点。对于node1,它先走headA对应的分叉和重合部分(若有的话),即全部的链表A的长度,之后从headB开始,走剩下的那个分叉。原创 2020-07-05 10:52:47 · 63 阅读 · 0 评论 -
题解七十三
剑指 Offer 53 - I. 在排序数组中查找数字 I统计一个数字在排序数组中出现的次数。示例 1:输入: nums = [5,7,7,8,8,10], target = 8输出: 2示例 2:输入: nums = [5,7,7,8,8,10], target = 6输出: 0限制:0 <= 数组长度 <= 50000(来源:力扣(LeetCode))思路:哈希表遍历一次数组,存入哈希表中,哈希表中的key为数组元素,value为数组元素出现的次数:(1)若数组元素原创 2020-07-04 13:06:27 · 93 阅读 · 0 评论 -
题解七十二
剑指 Offer 25. 合并两个排序的链表输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。示例1:输入:1->2->4, 1->3->4输出:1->1->2->3->4->4限制:0 <= 链表长度 <= 1000(来源:力扣(LeetCode))思路:递归我们通过递归调用来判断 l1 和 l2 头结点哪个更小,然后较小结点的 next 指针指向其余结点的合并结果,即,如果 l1 的 val 值更原创 2020-07-03 13:04:51 · 91 阅读 · 0 评论 -
题解七十一
剑指 Offer 45. 把数组排成最小的数输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。示例 1:输入: [10,2]输出: “102”示例 2:输入: [3,30,34,5,9]输出: “3033459”提示:0 < nums.length <= 100说明:1、输出结果可能非常大,所以你需要返回一个字符串而不是整数2、拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0(来源:力扣(LeetCode))思路:原创 2020-07-02 11:56:21 · 114 阅读 · 0 评论 -
题解七十
剑指 Offer 27. 二叉树的镜像请完成一个函数,输入一个二叉树,该函数输出它的镜像。思路:递归法。遍历二叉树,并交换左、右子节点,即可生成镜像二叉树:(1)若根节点root为空,则返回null;(2)设置一个变量tmp暂时保存左子树的子节点;(3)递归右子树子节点,并保存作为root的左子树子节点;(4)递归左子树子节点,记得是变量tmp,并保存作为root的右子树子节点(5)返回根节点root。class Solution { public TreeNode mirror原创 2020-07-01 17:08:09 · 73 阅读 · 0 评论 -
题解六十九
剑指 Offer 24. 反转链表定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL限制:0 <= 节点个数 <= 5000(来源:力扣(LeetCode))思路:递归(1)如果没有结点,或者只有一个结点,则直接返回,即if (node == null || node.next == null) r原创 2020-06-30 11:47:51 · 95 阅读 · 0 评论 -
题解六十八
剑指 Offer 18. 删除链表的节点给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。注意:此题对比原题有改动示例 1:输入: head = [4,5,1,9], val = 5输出: [4,1,9]解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.示例 2:输入: head = [4,5,1,9], val = 1输出: [4,5,9]解释: 给定你链表中值为 1 的原创 2020-06-29 11:13:14 · 87 阅读 · 0 评论 -
题解六十七
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。示例:输入:nums = [1,2,3,4]输出:[1,3,2,4]注:[3,1,2,4] 也是正确的答案之一。提示:1 <= nums.length <= 500001 <= nums[i] <= 10000(来源:力扣(LeetCode))思路:定义双指针left、right,分别指向数组的原创 2020-06-28 11:40:27 · 72 阅读 · 0 评论 -
题解六十六
122. 买卖股票的最佳时机 II给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。示例 1:输入: [7,1,5,3,6,4]输出: 7解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候原创 2020-06-27 11:41:44 · 62 阅读 · 0 评论 -
题解六十五
121. 买卖股票的最佳时机给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。注意:你不能在买入股票前卖出股票。示例 1:输入: [7,1,5,3,6,4]输出: 5解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股原创 2020-06-26 16:53:59 · 51 阅读 · 0 评论 -
题解六十四
714. 买卖股票的最佳时机含手续费给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。返回获得利润的最大值。注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。示例 1:输入: prices = [1, 3, 2, 8, 4, 9], fee = 2输出: 8解释: 能原创 2020-06-25 17:00:45 · 95 阅读 · 0 评论 -
题解六十三
877. 石子游戏亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] 。游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。亚历克斯和李轮流进行,亚历克斯先开始。 每回合,玩家从行的开始或结束处取走整堆石头。 这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。假设亚历克斯和李都发挥出最佳水平,当亚历克斯赢得比赛时返回 true ,当李赢得比赛时返回 false 。示例:输入:[5,3,4,5]输出:true解释:亚历克原创 2020-06-24 16:37:36 · 81 阅读 · 0 评论