剑指Offer
文章平均质量分 59
Java大数据运动猿
努力提升自己,记录学习过程。巩固自己,帮助他人!
展开
-
剑指 Offer 54. 二叉搜索树的第k大节点【37】
给定一棵二叉搜索树,请找出其中第k大的节点的值。原创 2023-05-03 11:56:26 · 650 阅读 · 0 评论 -
剑指 Offer 30. 包含min函数的栈【1】
1.设置两个栈对象A 和 B,A用来存储全部数据,B用来存储严格降序的数据原创 2022-11-24 11:05:28 · 572 阅读 · 0 评论 -
剑指 Offer 09. 用两个栈实现队列【41】
1.创建两个LinkedList链表当做栈,分别为stack1 和 stack2 ,stack1作为尾部添加元素、stack2作为删除元素。2.思路如下:(1)当stack2不为空时,在stack2中的栈顶元素是最先进入队列的元素,可以弹出。(2)当stack2为空时,同时stack1不为空,那么先把stack1中的元素逐个弹出并压入stack2中。由于先进入队列的元素被压到stack1的底端,经过弹出和压入操作之后就处于stack2的顶端,又可以直接弹出。原创 2022-11-24 10:29:55 · 244 阅读 · 0 评论 -
234. 回文链表【61】 == 剑指 Offer II 027. 回文链表
一共为两个步骤:复制链表值到数组列表中。使用双指针法判断是否为回文。1.我们需要遍历链表将值复制到数组ArrayList列表中。我们用 currentNode 指向当前节点。每次迭代向数组添加 currentNode.val,并移动链表指针currentNode = currentNode.next,当 currentNode = null 时停止循环。2.使用双指针法来检查是否为回文。我们在起点放置一个指针,在结尾放置一个指针,每一次迭代判断两个指针指向的元素是否相同,若不同,返回 fals原创 2022-11-22 10:41:35 · 160 阅读 · 0 评论 -
143. 重排链表【120】 == 剑指 Offer II 026. 重排链表
因为链表不支持下标访问,所以我们无法随机访问链表中任意位置的元素。我们利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。1.检查链表是否为空,创建一个返回值类型为ListNode的线性表。2.将链表中的结点逐个添加到线性表中。3.用while循环来重拍链表顺序,将链表后面的结点按题目规则进行移动,移动结点只需要改变指针指向即可。4.最后将最后一个指针指向null。原创 2022-11-20 11:16:54 · 510 阅读 · 0 评论 -
19. 删除链表的倒数第 N 个结点【110】 == 剑指 Offer II 021. 删除链表的倒数第 n 个结点
用快慢指针的方式:1.先创建一个头结点dummy指向链表第一个结点head2.创建fast、slow快慢指针,为了方便后面的删除,fast指向第一个结点head,slow指向dummy头结点,这样fast到链表尾部时,slow刚好指向需要删除的结点的前一个结点3.fast先走n步,然后快慢指针在while循环开始同时往后按逐个遍历,直到fast == null 时结束循环。这是slow指向要删除的前一个元素,将slow.next 指向slow.next.n原创 2022-11-19 12:20:49 · 476 阅读 · 0 评论 -
142. 环形链表 II【144】 == 剑指 Offer II 022. 链表中环的入口节点【0】
1.用快慢指针实现:(先判断是否有环,再求出入口结点位置)1.定义两个指针,一个fast快指针,一个slow慢指针,然后在判断是否有环(即fast是否等于slow)的循环里定义entry指针。2.快指针每次移动两个节点,慢指针每次移动一个节点,如果链表有环(即fast等于slow),快指针和慢指针会在某次移动时相遇,表示有环。3.然后在判断有环中创建entry指针,entry指针从头节点开始往后遍历,slow指针从与fast指针相遇的地方继续往后遍历,直到slow与entry指针相遇即为入口。原创 2022-11-18 15:32:13 · 165 阅读 · 0 评论 -
剑指 Offer 18. 删除链表的节点【4】
删除链表分三种情况:1.删除第一个位置的结点2.删除中间以及最后位置的结点3.链表中没有要删除的结点思路:1.删除第一个结点,直接返回链表下一个结点即可2.删除中间或最后位置的结点,首先设置两个指针,pre和cur指针,pre指向前一个结点,cur指向当前结点,用while循环遍历链表,判断是否是要删除的结点,找到了就跳出循环,然后将当前结点的前一个结点pre指向下一个结点cur.next;3.跳出循环后,判断一下cur是否为null,为null则表示链表中没有要删除的结点,则返原创 2022-11-17 12:32:42 · 231 阅读 · 0 评论 -
剑指 Offer 22. 链表中倒数第k个节点【91】
快慢指针解法:1、初始化两个指针former和latter,一开始都指向链表的头节点2、前指针former先向前走 k 步3、两个指针former和latter同时向前移动,直到前指针former指向NULL4、最后返回latter疑惑解答:(1)这里代码先走k步,而不是先走k-1步;(2)为什么循环条件是former != null,却不是former.next != null答:参考动画里的图示,因为latter是走到最后一个节点的后一个位置,是null位原创 2022-11-17 12:06:15 · 183 阅读 · 0 评论 -
160. 相交链表【168】 == 剑指 Offer 52. 两个链表的第一个公共节点【20】
1.设置两个头指针PA、PB分别指向链表A、链表B2.PA遍历链表A,当遍历到链表A尾部时,将headB头指针赋值给PA,PA开始遍历链表B;3.PB也一样,PB遍历链表B,当遍历到链表B尾部时,将headA头指针赋值给PB,PB开始遍历链表A;4.如果两个链表中有公共的结点,PA和PB将会在某一处相遇,判断PA和PB是否相等即可;5.如果两个链表中没有公共的结点,那PA和PB都将会遍历到链表的尾部,链表的尾部为null,那么PA、PB也会相当,但返回的是null。原创 2022-11-17 11:39:32 · 189 阅读 · 0 评论 -
21. 合并两个有序链表【221】 == 剑指 Offer 25. 合并两个排序的链表【6】
1.L1和L2两个递增的链表合并成一个递增的链表,将L1和L2链表的结点从头到尾依次比较,如果L1小,就将next指向L1的那个元素,然后指针后移一位,再跟L2那个元素比较,如果L2大,就将next指向L2,指针在L2链表上后移,循环遍历,直到有一个链表遍历完成2.这时会有一个链表还有剩余结点,将剩余结点直接接在新链表后面即可。原创 2022-11-16 11:59:31 · 155 阅读 · 0 评论 -
剑指 Offer 06. 从尾到头打印链表【2】
由题意知,第一个遍历到的结点最后一个输出,最后一个遍历到的结点第一个输出,则想到栈“后进先出”的思想,这里可以用栈来实现。1.构建一个栈,构建一个指针“头结点”2.循环遍历链表的每一个结点,把结点放入栈中3.获取栈的长度,创建等长数组,最后把栈中数据循环遍历放入数组中,返回数组。原创 2022-11-16 10:30:55 · 167 阅读 · 0 评论 -
206. 反转链表【529】==剑指 Offer 24. 反转链表【13】
两种方式:1.定义反转头来实现 2.递归方式实现(比较难懂)1.定义反转头实现:思路:先创建一个反转头结点,然后将正序链表中的结点从前到后依次放入反转链表中,// 同时,每次将结点放入反转链表都是插入到第一个结点,与反转头节点直接相连,// 这里用循环逐个插入,最后将现有的头结点指向反转后的第一个结点即可。2.递归方式实现(比较难懂)思路:递归反转就是从原链表的第一个存储节点开始,依次递归调用反转每一个结点,// 直到把最后一个反转完毕,真个链表就反转完毕了。原创 2022-11-16 11:12:08 · 335 阅读 · 0 评论 -
剑指 Offer 57 - II. 和为s的连续正数序列【9】
思路,双指针(left左指针 right右指针)刚开始 left 在位置 1, right 在位置 2, 定义左右指针之间的数字和为:sum = n*(a1+an)/2 递增数列的求和公式1.类似二分查找的逻辑,当 sum 等于 target 时,将左右指针之间的这种数组加入结果,然后左指针右移2.当 sum 小于 target 时,右指针右移增大 sum3.当 sum 大于 target 时,说明以 left 为起点组成的数组不符要求,左指针右移原创 2022-10-27 11:54:27 · 154 阅读 · 0 评论 -
剑指 Offer 57. 和为s的两个数字【2】
条件:递增排序数组,找出两个数字相加和为给定的值s因为是递增排序的数组,所以我们可以用双指针来解题,left指针和right指针left指向数组最左元素,right指向数组最右元素。用左指针元素和右指针元素相加的结果来判断指针移动。while(left < right){如果两个元素相加等于目标值,则直接返回如果两个元素相加大于目标值,则右指针向左移动。如果两个元素相加小于目标值,则左指针向右移动}原创 2022-10-27 11:18:24 · 528 阅读 · 0 评论 -
剑指 Offer 40. 最小的k个数【31】
在排序过程中,我们可以去不断的缩小排序的区间,这里我们借助快速排序的代码,稍微的改动几行就完成了这道题目。1、以当前区间的第一个元素为基准元素pivot,根据快速排序的操作,将当前区间划分为了三个区间。1、左侧区间均是小于等于基准元素pivot的元素2、中间区间均是等于基准元素pivot的元素3、右侧区间均是大于等于基准元素pivot的元素原创 2022-10-27 10:51:40 · 891 阅读 · 0 评论 -
剑指 Offer 44. 数字序列中某一位的数字【2】
1.序列前9位为单位数 9个数2.序列10-99为双位数 90*2=180个3.序列100-999为三位数 900*3=2700个数4.序列1000-9999为四位数 9000*4=3600个数比如要找第1001位数,可以这样计算:(1001-180-9=881)、881=270*3+1原创 2022-10-26 13:17:16 · 445 阅读 · 0 评论 -
剑指 Offer 49. 丑数【2】
可以用空间换时间的方式,创建数组保存已经找到的丑数。根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此,我们可以创建一个数组,里面保存的是排好序的丑数,每一个丑数都可以由前面的丑数乘以2、3或者5得到。这个题用三个指针,第一个丑数是1,以后的丑数都是基于前面的小丑数分别乘2,3,5构成的。我们每次添加进去一个当前计算出来个三个丑数的最小的一个,并且是谁计算的,谁指针就后移一位。原创 2022-10-26 11:43:24 · 484 阅读 · 0 评论 -
剑指 Offer 61. 扑克牌中的顺子【19】
1、设置一个哈希表Set,借助它来执行判重操作,判断这 5 张牌是否存在重复牌,如果存在,那么肯定就不是顺子了。2、设置两个变量 Max、Min,用来记录这五张牌除了 0 之外的最大值和最小值。3、遇到大小王,忽略它。4、遇到非大小王的牌,检查哈希表是否存在这张牌,如果存在,那么肯定就不是顺子,直接返回false,否则将它加入到哈希表中,同时更新最大牌、最小牌的值。5、遍历完毕之后,判断 Max、Min 是否小于 5。原创 2022-10-26 10:23:44 · 332 阅读 · 0 评论 -
剑指 Offer 62. 圆圈中最后剩下的数字【29】
递推公式: f[1]=0; f[i]=(f[i-1]+m)%i; (i>1)原创 2022-10-26 09:24:51 · 159 阅读 · 0 评论 -
剑指 Offer 64. 求1+2+…+n【2】
利用与运算的短路特性,所谓短路,比如 A && B,当A条件不成立时,不论B是否成立,结果都是false,所以B不再进行计算,利用短路特性可以实现递归停止,进而求出和。原创 2022-10-24 12:11:30 · 153 阅读 · 0 评论 -
剑指 Offer 12. 矩阵中的路径【8】
1.先在矩阵中逐个元素遍历找出要查找字符串的第一个字符的元素的位置2.从那个元素位置开始进行上左下右的匹配(1)如果匹配成功就进入字符串的下一个字符的匹配,同时标记此元素为#,防止再次匹配到这个元素(2)如果匹配不成功,则退回上一个匹配成功的位置重新进行查找,也就是换一条路径。3.重复上述步骤2的操作,用递归的方式,直到找到最后一个字符串元素,返回true,否则返回false。原创 2022-10-23 09:58:37 · 307 阅读 · 0 评论 -
剑指 Offer 47. 礼物的最大价值【2】
在元二维数组的空间上,进行替换,从左上角开始向下向左,dp[i][j] = girl[i][j] + 前一个元素,然后取最大值(从左向右加当前元素的最大还是从上到下加当前元素的大)原创 2022-10-22 10:41:12 · 157 阅读 · 0 评论 -
剑指 Offer 14- I. 剪绳子【8】
数论任何大于1的数都可由2和3相加组成(根据奇偶证明)因为2*2=1*4,2*3>1*5, 所以将数字拆成2和3,能得到的积最大因为2*2*2原创 2022-10-22 09:25:36 · 319 阅读 · 0 评论 -
变态跳台阶【35】
当只有一级台阶时,f(1)=1;当有两级台阶时,f(2)=f(2-1)+f(2-2);一般情况下,当有n级台阶时,f(n)=f(n-1)+f(n-2)+···+f(n-n)=f(0)+f(1)+···+f(n-1),同理,f(n-1)=f(0)+f(1)+···+f(n-2). 因此,根据上述规律可以得到:f(n)=2*f(n-1)。这时一个递推公式,同样为了效率问题,用循环可以实现。原创 2022-10-19 15:43:00 · 124 阅读 · 0 评论 -
剑指 Offer 10- II. 青蛙跳台阶问题【35】
在一般情况下,可以把n级台阶的跳法看成n的函数,记为f(n),那么一般情况下,一开始我们有两种不同的选择:(1)第一步只跳一级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即f(n-1);(2)第一步跳两级,那么跳法数目等于后面剩下的n-2级台阶的跳法数目,即f(n-2)。所以f(n)=f(n-1)+f(n-2)。原创 2022-10-19 14:34:00 · 246 阅读 · 0 评论 -
剑指 Offer 10- I. 斐波那契数列【33】
改进循环算法: 斐波那契数列:0,1,1,2,3,5,8........ 总结起来就是:第一项是0,第二项是1,后续第n项为第n-1项和第n-2项之和。也就是0开始,往后计算,从下层往上层递增,算到哪就把值保存,然后直接进入下一环节的计算,而不是重新计算。原创 2022-10-19 13:49:51 · 254 阅读 · 0 评论 -
剑指 Offer 56 - I. 数组中数字出现的次数【2】
分两步:1.将数字异或,任何一个数字异或它自己都等于0,而0异或任何数都等于那个数。2.把数组分成两个子数组,使每个子数组包含一个只出现一次的数字,而其他数字成对出现原创 2022-10-18 15:44:25 · 188 阅读 · 0 评论 -
3. 无重复字符的最长子串【539】== 剑指 Offer 48. 最长不含重复字符的子字符串【15】
滑动窗口(双指针)+HashMap记录重复字符位置左右指针,左指针指向重复元素,右指针从左向右遍历,用HashMap判断元素是否为重复元素。原创 2022-10-18 14:54:58 · 276 阅读 · 0 评论 -
剑指 Offer 38. 字符串的排列【12】
递归、分两步。1. 先求出所有可能出现在第一个位置的字符,然后用第一个字符和后面所有字符交换。2. 固定第一个字符,让第二个字符和它后面所有的字符交换,以此类推。原创 2022-10-18 13:54:51 · 138 阅读 · 0 评论 -
剑指 Offer 20. 表示数值的字符串【2】
判断条件:‘.’出现正确情况:只出现一次,且在e的前面,‘e’出现正确情况:只出现一次,且出现前有数字,‘+’‘-’出现正确情况:只能在开头和e后一位原创 2022-10-15 10:04:52 · 553 阅读 · 0 评论 -
剑指 Offer 50. 第一个只出现一次的字符【9】
(1)用HashMap集合: 用 HashMap 添加每个字符与其出现的值,出现一次为true,出现两次及两次以上为false,然后再依次遍历字符串时,找到第一个出现值为true的字符,返回即可。(2)用字符数组:因为该字符串全部是字母,所以可以用一个字符数组代替哈希表,数组下标就代表该字母。然后遍历字符串,在数组对应下标的地方为值加1,最后返回第一个值为1的下标。原创 2022-10-11 18:19:39 · 155 阅读 · 0 评论 -
剑指 Offer 58 - II. 左旋转字符串【2】
定义一个翻转函数,总共调用三次即可完成翻转。1.反转区间为前n的子串2.反转区间为n到末尾的子串3.反转整个字符串原创 2022-10-11 17:04:00 · 127 阅读 · 0 评论 -
剑指 Offer 58 - I. 翻转单词顺序【5】
定义一个双指针函数,用来翻转字符串。先将整个字符串翻转,然后再逐一地对单词进行翻转,用空格判断是否是一个单词。最后一个单词末尾没有空格,所以在最后直接翻转。原创 2022-10-11 16:27:29 · 291 阅读 · 0 评论 -
剑指 Offer 05. 替换空格【3】
1. 先计算新数组总的长度,由于空格换成 "%20",所以每个空格会额外多出两个字符。所以新的长度 = 原来长度 + 空格数 * 2。 2. 准备两个指针 P1, P2。P1 指向原始字符串的末尾,P2 指向新字符串的末尾。 3. 接下来向前移动指针 P1,逐个把它指向的字符复制到 P2 指向的位置,直到碰到了第一个空格为止。碰到第一个空格后,把 P1 向前移动 1 格,在 P2 之前插入字符串 "%20"。由于 "%20" 的长度为 3, 同时也需要把 P2 向前移动 3 格。原创 2022-10-10 12:40:10 · 399 阅读 · 0 评论 -
剑指Offer数组篇-----刷题总结
数组类题大多数都是用指针来解题的,比如双指针、二分法、还有多个指针的。数组类题解题思想就是借助它是一块连续的内存空间来解题,按照下标元素的规律,再加上指针来解题。其中查找类题大都是二分查找的思想,遇到数组类题先想着用双指针、二分查找思路,不行再考虑别的思路。原创 2022-10-10 11:20:15 · 236 阅读 · 0 评论 -
剑指 Offer 53 - II. 0~n-1中缺失的数字【5】
利用二分查找+递归思想首先数组0-n-1中数值是有序的,只有其中一个数不在数组中,设它为m,则m之前的数值与下标都是相等的,m之后的数值都比下标大1,即m+1、m+2......二分法求解(1)中间元素值等于下标元素,则目标对象在后半部分(2)中间元素值不等于下标元素,则目标对象在前半部分接着不断二分下去,直到找到元素。原创 2022-10-09 16:26:26 · 156 阅读 · 0 评论 -
剑指 Offer 53 - I. 在排序数组中查找数字 I【18】
二分查找法 target:目标值1.如果中间数字比target大,那target只能出现在数组的前半段2.如果中间数字比target小,那target只能出现在数组的后半段3.如果中间数字等于target,那就寻找左右两边target的值,左右两边同时遍历数组,直到找到目标元素,指针停止。原创 2022-10-09 14:37:12 · 164 阅读 · 0 评论 -
剑指 Offer 45. 把数组排成最小的数【17】
1.先将整型数组转为字符串数组(防止数字过大溢出)2.再用快速排序、递归的思想,定一个pivot基准值,分出left、right两个区域,递归不断分下去,将左右两块区域的元素移动,最终另左边任意元素与pivot组合都小于pivot在前,右边任意元素与pivot组合都大于pivot在前。原创 2022-10-09 10:30:44 · 225 阅读 · 0 评论 -
53. 最大子数组和【235】== 剑指 Offer 42. 连续子数组的最大和【31】
dp[ i ]=max(dp[ i-1]+data[ i ],data[ i ]). 这个公式的含义是:当以第i-1个数字结尾的子数组中所有数字的和小于0时,把这个负数与第i个数累加,则得到的和比第i个数字本身还要小,所以这种情况下dp[ i ]就是第i个数字本身。反之,如果以第i-1个数字结尾的子数组中所有数字的和大于0,则与第i个数字累加就得到以第i个数字结尾的子数组中所有数字的和。原创 2022-10-05 15:56:12 · 534 阅读 · 0 评论