自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(54)
  • 收藏
  • 关注

原创 剑指 Offer 68 - II. 二叉树的最近公共祖先

//这个题目的二叉树是普通的二叉树,没有规律,因此理论上这两个节点在哪我们不知道。只能遍历查找到节点, //如果找到了就返回那个节点,到底也没找到就返回null,最后递归完回来时在每层都判断是否符合。按照这个思路,如果他们的祖先节点是p、q中的一个,它被return到上一层了,此时其他的路都是null,所以最终应该返回它。如果他们的祖先节点不是p、q中的一个,p、q被返回到上层时,总有一层会有节点捕获到左右节点同时不为null,返回这个节点。再往上层走,其他路都为nu...

2022-04-04 20:52:15 576

原创 剑指 Offer 66. 构建乘积数组

思路:使用类似动态规划的方法,使用一个数组来记录每一行乘的结果。分为右上和左下两个区域。左下区域,下一行乘得的结果=上一行结果*a(i-1)。右上使用一个数字保存乘积结果,并且与左下乘积结果得到的数组相乘,得到最终结果。class Solution { public int[] constructArr(int[] a) { if(a==null || a.length==0){ return new int[0]; ...

2022-04-02 22:38:21 240

原创 剑指 Offer 64. 求1+2+…+n

不让使用判断符去实现,可以选择使用判断条件来完成:随便设置一个boolean变量,要想跨过这个语句就必须执行完右边的判断。而右边正是递归的语句。因此它会一直递归,直到n==0时,与运算左边判断失败,不会进入与运算右边。直接给bb赋值false;进入下一步。最底层的方法执行完,倒数第二层从sumNums中出来,也继续执行加法。最终可以得到和。class Solution { int sum=0; public int sumNums(int n) ...

2022-04-01 17:39:56 208

原创 剑指 Offer 63. 股票的最大利润

经典利润问题,计算每一步的盈亏情况。如果亏钱了就归零。如果赚钱了就比较并且记录下来最大的利润。class Solution { public int maxProfit(int[] prices) { if(prices==null || prices.length==0){ return 0; } //股票最大利润问题 //首先计算每一步的盈亏状况 int[] arr =...

2022-04-01 17:01:34 193

原创 剑指 Offer 61. 扑克牌中的顺子

思路是这样的:先判断是不是长度为5的数组。除了0之外有没有重复的数?如果有,肯定不是顺子。如果没有重复的,除了0之外的最大值减去最小值是不是≤4.例如: 1 2 3 4 5 此时max-min等于4.30 5 0 0 max-min=2,因为除了0之外已经没有重复的数了,最大值减去最小值就是当前的范围。不用管中间的数是不是存在。只要max-min不大于4,那么就能使用0来补齐顺子。使用set来存储class Solution { public ...

2022-04-01 15:27:18 95

原创 剑指 Offer 58 - II. 左旋转字符串

使用String跟StringBuilder的dpi可以比较简单的实现这个需求。class Solution { public String reverseLeftWords(String s, int n) { if(s==null||s.length()==0){ return ""; } if(n<=0 || n>=s.length()){ return s;...

2022-03-31 14:54:48 56

原创 剑指 Offer 58 - I. 翻转单词顺序

刚开始想复杂了,脑子里全是两次反转,最后发现两次反转太麻烦了 效率也低:class Solution { public String reverseWords(String s) { if(s==null || s.length()==0){ return ""; } String ss= s.trim(); //首先想到的是两次反转,第一次大反转后,遍历字符串,去掉空格 将每个单词进行...

2022-03-29 22:03:59 156

原创 剑指 Offer 57 - II. 和为s的连续正数序列 滑动窗口规律

滑动窗口求解。规律:一个有序排列的数组,求两个数的和,可以考虑使用两个指针在两端,向中间移动。如果两个指针的和大于目标数,说明两下标之间的任意数与右下标数的和一定大于目标数,那么就淘汰右下标的数,即右指针向左移动一位。再进行比较,同理,如果两个指针的数之和小于目标数,就将左标向右移动一位,再进行比较。结束条件是left≥right。 如:1,3,5,6,7,8 target=10;一个有序排列的数组,求很多连续数字的和。可以使用两个指针(left,right)都从左边第一个...

2022-03-29 20:35:24 171

原创 剑指 Offer 57. 和为s的两个数字

class Solution { public int[] twoSum(int[] nums, int target) { //两数之和问题,首先想到使用set记录。 效率不是很理想 注意到题中递增排序的数组。那么 if(nums==null || nums.length==0){ return null; } HashSet<Integer> set = new HashSe...

2022-03-27 21:51:44 102

原创 剑指 Offer 56 - II. 数组中数字出现的次数 II

使用map的方法:class Solution { public int singleNumber(int[] nums) { //数组中一个数字出现一次,剩下的数字都出现了三次,要找到那个只出现一次的数字 //首先想到的是map记录每个数出现多少次。 if(nums==null || nums.length==0){ return 0; } HashMap<Integer,Int..

2022-03-27 20:55:17 88

原创 剑指 Offer 56 - I. 数组中数字出现的次数

//首先,空间复杂度1,说明不能使用map存储了。题意得知很多重复的元素,要寻找单个元素。可以使用异或运算。即使不在一起,两个相同的数进行异或运算也可以消掉。 //使用异或运算。然后把数组分为两份 //(异或得到的结果找到哪一位不为0,说明这一位两个数不一样。 //根据这一位把数组分为两份,两个只出现一次的数肯定分别位于两个数组中), //这两个数字分别在两个数组中,分别对数组进行运...

2022-03-27 20:27:03 103

原创 剑指 Offer 55 - II. 平衡二叉树 题解

可以使用求树的深度的方法,求出每一个叶节点的深度,进行比较。也可以递归,从底到根看左右节点是不是平衡,如果平衡,那么就返回下面有几层。如果不平衡就返回-1,方法中左右节点获得的返回值如果是-1,就说明存在不平衡的情况,不需要往下执行。直接返回-1即可。最终方法得到的值如果是-1,说明不平衡。/** * Definition for a binary tree node. * public class TreeNode { * int val; * Tre...

2022-03-27 17:29:11 297

原创 剑指 Offer 55 - I. 二叉树的深度 题解

/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */class Solution { int max = 0; public int maxDepth(TreeNode ro...

2022-03-27 15:37:33 292

原创 剑指 Offer 54. 二叉搜索树的第k大节点 题解

/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */class Solution { Stack<Integer> stack1 = new Stack<>()...

2022-03-27 15:21:37 52

原创 剑指 Offer 53 - II. 0~n-1中缺失的数字 题解

class Solution { public int missingNumber(int[] nums) { //二分法 找到位数与数字不相等的第一个数字,减去1即为所求 if(nums==null || nums.length==0){ return -1; } return findNumber(nums,0,nums.length-1); } public int find...

2022-03-27 14:41:22 51

原创 剑指 Offer 53 - I. 在排序数组中查找数字 I 题解

二分法找到目标 左右寻找。直接拿下!!!class Solution { public int search(int[] nums, int target) {//二分法 查找 if(nums==null || nums.length==0){ return 0; } return binarySearch(nums,target,0,nums.length-1); } public int binarySearch(int...

2022-03-26 23:57:40 49

原创 剑指 Offer 51. 数组中的逆序对 题解

思路:使用普通的暴力解法会超时。选择使用归并算法(分治的思想)来解决这个问题。归并算法是将两个排好序的子数组中的元素进行排序。选择两个数组首部较小的一个放入新创建的数组当中。此时就能利用这个机制来实现题目要求。当后面一半数组第一个元素小于前面数组首部元素时,判断前半数组中还有多少个元素n,就是在这两个数组所有元素中,有n个数在该数前面,并且比它大。将所有n加起来,即题目中总的逆序对的数目。思路就是后一个数组中有元素要放入数组时,看看前一半数组中还有几个没有放进去。就是有几个比它大,组成逆序对。...

2022-03-25 22:20:24 137

原创 剑指 Offer 50. 第一个只出现一次的字符 题解

简单题,耗时10min。想要找到第一个只出现一次的字符,第一次遍历的时候肯定不知道后面有没有这个字符,所以首先遍历一次后,得到每个字符出现的次数,题目中给了限制:所有字符都是小写英文字母。只有26个。可以使用一个长26的数组来储存每个字符出现的次数。因为要得到第一个出现的字符,那么第二次循环从前到后读取字符,拿到它存储在数组中的出现次数。如果为1,那么返回这个字符。如果循环结束后都没有符合条件的,就说明找不到,返回一个空格字符。class Solution { public cha

2022-03-25 20:19:59 58

原创 剑指 Offer 45. 把数组排成最小的数 题解

class Solution { public String minNumber(int[] nums) { //思路:比较这些数的最高位、第二位 从小到大排应该 第一位一样的比较第二位,前面都一样,位数少的优先。 //24,103,9,20,2,29,12,210 //30 3035 if(nums==null||nums.length==0){ return ""; } i.

2022-03-24 23:57:28 70

原创 剑指 Offer 49. 丑数 题解思路

第一时间没想出来。丑数是由2 3 5 相乘得到的。那么就可以回溯计算前n个丑数。初始值是1,1*2,3,5 拿到最大值2,当做第二个数。下一次就是1*3,1*5和2*2相比较拿到最大值。可以看做是三个数列,拿他们的头部作比较,从小到大排序。三个数列分别是由一个array数列每一位乘2 3 5 得到的。array数列是动态构造出来的,拿第i个丑数当做array【i-1】。class Solution { public int nthUglyNumber(int n) { ..

2022-03-24 13:06:37 66

原创 剑指 Offer 48. 最长不含重复字符的子字符串 思路题解

思路:最初的思路是创建一个map,一个maxSon(int),循环将每一位字符与其下标存进去。存入之前判断这一个字符是否已经存在表中。如果不存在就直接加入,存在的话获取已经存在的该字符其下标t,可计算当前最大不重复字符串长度,与max作比较后取较大值maxSon。 之后把循环的下标移到t,清空集合map。下一循环就重新计数了。这个方法比较笨。可以选择不清空集合map,通过下标的计算来实现 动态规划的思路。新加一个临时变量max,用于表示当前最大的无重复字符串长度...

2022-03-24 12:19:35 287

原创 剑指 Offer 42. 连续子数组的最大和

class Solution { public int maxSubArray(int[] nums) { if(nums==null || nums.length==0){ return 0; } int sum=-101; int temp=0; for(int i:nums){ temp= i+temp; if(sum<temp){.

2021-12-11 22:32:54 327

原创 数据流中的中位数

class MedianFinder { /** initialize your data structure here. */ PriorityQueue<Integer> left; PriorityQueue<Integer> right; public MedianFinder() { left=new PriorityQueue<Integer>((x,y)->y-x); right =.

2021-12-11 22:07:06 254

原创 剑指 Offer 37. 序列化二叉树 思路与代码

思路:这一个问题需要分两步:1.序列化:把二叉树变成一个字符串。可以使用层序遍历或者前序遍历。代码选择使用层序遍历,注意null也要加进去,否则无法重构二叉树。2.反序列化:把字符串分割成数组,使用一个m计算出现了多少个null,计算子节点的时候就-2*m。 另一个思路是使用一个队列。null就直接跳过,数就构建树后 加入队列。如果使用前序遍历,注意把null也遍历进来。在反序列化的时候,使用递归,将字符串变成 存着值得 List,判断 节点为 null就return nul...

2021-12-02 18:09:03 186

原创 剑指 Offer 36. 二叉搜索树与双向链表 思路与代码

思路:遇到类似的题,没见过没关系,不要慌!先分析它给出的结构与需要的结构各有什么特点?一定是根据各自的特点去写代码。可以看到给的数是一个二叉搜索树,二叉搜索树有什么特点呢?二叉搜索树的左子树都小于这个节点,右子树都大于这个节点。它的中序遍历是从小到大遍历的。题目需要的是什么结构?是一个双向的循环链表,而且是一个有顺序的。这个特点跟二叉搜索树中序遍历不谋而合,分析到这就很明朗了,十有八九就是利用中序遍历解决问题!!中序线索化二叉树与这个类似。可以定义一个前置节点pre,使用flag记录...

2021-11-29 22:13:31 48

原创 剑指 Offer 35. 复杂链表的复制 思路与代码

思路:这一题最开始没想出来,想了很久都觉得很复杂。看了答案有两个方法:1.使用递归和哈希表,创建一个哈希表,key为原链表中的元素,value为复制链表中的元素。递归判断,是否存在key。如果存在key 就说明已经创建了该复制节点,拿到复制节点。如果不存在key,说明没有创建该复制节点,应该new一个节点,next 和random都调用递归方法拿到。最终拿到的headcopy就是满足题意的。2.第二个方法使用复制双节点的方法,很巧妙。需要遍历三次:首先第一次遍历,把链表每一...

2021-11-27 22:32:39 4012

原创 剑指 Offer 33. 二叉搜索树的后序遍历序列 思路与代码

思路: 遇到这种问题,要先想想这个结构有什么特点。也就是它是什么样结构,它后序遍历的数组有什么特点? 可以看到规律,数组中最后一个元素总是树的根节点,并且它前面的数组中前一部分都小于它,后一部分都大于它。如果满足这个,就可以递归判断。直到数组中只有2个元素或者1个元素(必定可以组为二叉排序树)。 每一层都使用递归判断是否符合二叉排序树后序遍历的规律,最终可以返回结果。class Solution { public boolean verifyPostorder(int[] po...

2021-11-25 13:14:35 238

原创 剑指 Offer 32 - III. 从上到下打印二叉树 III 思路与代码

思路:需要将奇数行正序输出,偶数行倒叙输出。可以使用双端队列,双端队列可以控制加入与移除的是第一个还是最后一个。因此我们可以加入一个count,每次循环便加1,用来判断这一层是奇数还是偶数。如果为奇数,那么就将每一个数据加入到双端队列的最后面。得到的为正序。如果为偶数,那么将每一个数据加入到双端队列的最前面,得到的为倒序。这样就完成了树的正序与倒序的输出。还可以控制que那一个双端队列的API,实现这个功能。也可以正常输出,在加入到list前判断...

2021-11-24 22:13:44 337

原创 剑指 Offer 32 - II. 从上到下打印二叉树 II 思路与代码

思路:这一题需要每一行的元素在一起输出。可以使用队列来记录,队列的长度为该行元素的个数(n)。循环n次,为一行。把该行元素存入temp的集合中,循环结束加入list当中。判断如果队列不为空,那么开启下一次循环,新建一个temp集合,继续循环队列的长度n次。把元素放入temp集合当中。直到队列为空,说明所有元素都被遍历了。 写代码的时候遇到了一个容易被忽视的点:我想在前面把temp建好,每次temp.clear(),把集合清空再循环。这里很容易想错,每一个循环中temp都指向一个地...

2021-11-23 23:29:30 56

原创 剑指offer 32 从上到下打印二叉树 思路与代码

思路:层序遍历,思路很简单,新建一个队列,如果节点不为空,就把节点的左节点与右节点加入队列。每次循环从队列中取出最前面的节点输出。直到队列为空为止。/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } *...

2021-11-23 22:20:53 58

原创 剑指 Offer 29. 顺时针打印矩阵 思路与代码

思路:首先可以明确需要输出多少个数是知道的。也就是行数*列数。我的思路是定义四种状态,上下左右。同时定义四个边界。让一个指针在边界围成的空间中按照四种状态移动。每次移动到边界,改变其状态,同时移动边界。直到输出结束。思路和代码都比较简单另外还可以使用画框的方式:大框走一圈,把边界往中间移一圈。此时开始的坐标为原坐标的右下位置。同样也需要有边界限制。可以通过判断起点是否位于边界之外判断是否循环结束。class Solution { ...

2021-11-22 22:53:22 188

原创 剑指 Offer 31. 栈的压入、弹出序列 思路与代码

思路:模拟栈弹出的过程。通过popped数组监控栈的情况。如图中实例2,栈第一个弹出的元素是4,那么就把pushed中的指针移到5的下方。把1,2,3,4都放入栈中。再判断下一位popped【i】与栈顶元素相同吗?如果不相同,就让pushed的下标往后移,同时把元素加入栈,直到遇到与popped【i】相等的数,或者到达数组边界为止。如果相同,就pop()该元素,继续循环。循环结束,判断栈是否为空,如果为空,说明按照规则弹出加入,返回true。...

2021-11-21 21:52:51 211

原创 剑指 Offer 27. 二叉树的镜像 代码与思路

思路:看到树,第一时间要想到递归。使用递归的方法,前序遍历,把每一个节点的左右子树都进行交换。最后拿到的根节点就是所需要的树。 还可以使用栈的方法,遍历存储所有节点,再弹出交换所有节点的左右子树。/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeN...

2021-11-21 20:53:27 193

原创 剑指 Offer 26. 树的子结构 思路与代码

思路:由题意可知,我们需要判断树B是不是树A的子树。不管怎么样,肯定要在树A中找到与B树根节点val值相等的节点。可以选择递归或者非递归的遍历。找到节点值与树B根节点val值相等的节点。进入compare递归判断它们的结构是不是相等的(注意:在递归时如果某次递归B节点为空,那么不管A是不是空,肯定返回true。如果B节点不为空,判断如果A节点为空,那么肯定返回false。两个都不为空的情况下,判断两节点的值是不是相等的,如果是相等的,继续左节点、右节点调用compare递归...

2021-11-18 22:23:05 318

原创 剑指 Offer 25. 合并两个排序的链表 思路和代码

思路: 新建一个链表头结点。两个指针分别在两个链表头部,比较哪一个小。把小节点放到新的空 头结点下一位。然后新链表与小的节点所在的链表的指针都向后移一位。再次比较。直到某一个链表到尾部。将另一个还未到头的链表的指针所在节点直接接到新链表尾部。 这里我原先是遍历加入的,后来看到可以直接把剩余链表的尾部直接接到新链表尾部。这个方法更好! 最后返回新链表头结点的next节点即可。/** * Definition for singly-linked list....

2021-11-18 21:38:04 399

原创 剑指 Offer 24. 反转链表 思路与代码

思路: 倒着输出首先想到的是栈,但是栈需要遍历两次,且需要n的空间来储存链表。可以利用三个指针来一边遍历,一遍改变指针的指向。1 2-> 3 把Node2的next指向1时,相当于截断了链表,因此需要第三个指针在截断前,保存Node3。最终cur==null 时,pre就是所要的链表的头结点。/** * Definition for singly-linked list. * public class ListNode { * int val...

2021-11-17 22:53:53 4003

原创 剑指 Offer 22. 链表中倒数第k个节点 思路和代码

思路:倒着数第k个,两个指针,先让一个指针前进k-1,再一起前进,先走的那个指针走到最右边,这时走得慢的指针所在的位置就是所求的倒数第k个。注意,要考虑特殊情况,养成好习惯。(k的值大于链表长度,k小于等于0,链表为空)/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { ...

2021-11-17 22:24:13 320

原创 剑指offer 21 调整数组顺序使奇数位于偶数前面 思路与代码

思路:数组前面和后面属性不一样,前面是奇数,后面是偶数,可以想到利用两个指针前后进行判断和交换。保证左指针的左边一定是奇数,右指针的右边一定是偶数。结束条件就是两个指针相遇。代码如下:class Solution { public int[] exchange(int[] nums) { if(nums==null || nums.length==0){ return nums; } //奇数在前面 偶数...

2021-11-17 22:15:03 56

原创 剑指 Offer 20. 表示数值的字符串 思路与代码

思路:这类题需要考虑的情况特别多,一时间很难考虑周到,因此要做好不断完善代码的准备。把输入的字符串先trim() 一下,去除两端的空格。整体转换为一个char类型的数组cc。之后从头到尾遍历这个数组,判断处于什么情况。判断的指标整体分为三个:遇到点了吗,遇到e/E了吗,遇到数字了吗。可以根据这个思路写代码,把正常的情况全部通过,其余的都直接返回false。需要注意的典型错误情况为:点前后都没有数字。e前没有数字(这两个可以直接用isnum的值来判断)。正负号应...

2021-11-14 22:53:41 187

原创 剑指 Offer 18. 删除链表的节点 思路与代码

思路:使用一个或者两个指针定位,检测head节点val是否等于value,如果等于就直接返回head.next。检测指针的下一个节点val值是不是等于val,倘若等于,就另指针的下一个元素指向下下个元素(可能为null,不影响),此时返回head节点即可。 循环到结束没找到符合条件的节点,也直接返回head即可。注意:假如题中给的不是val值,而是要删除的节点,则判断节点的next是不是null,如果是null。从head开始遍历,找到这个节点的上个节点,令其next=...

2021-11-08 21:57:14 189

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除