![](https://img-blog.csdnimg.cn/20201014180756923.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
java练习
mmmmmao77
这个作者很懒,什么都没留下…
展开
-
剑指 Offer 68 - II. 二叉树的最近公共祖先
//这个题目的二叉树是普通的二叉树,没有规律,因此理论上这两个节点在哪我们不知道。只能遍历查找到节点, //如果找到了就返回那个节点,到底也没找到就返回null,最后递归完回来时在每层都判断是否符合。按照这个思路,如果他们的祖先节点是p、q中的一个,它被return到上一层了,此时其他的路都是null,所以最终应该返回它。如果他们的祖先节点不是p、q中的一个,p、q被返回到上层时,总有一层会有节点捕获到左右节点同时不为null,返回这个节点。再往上层走,其他路都为nu...原创 2022-04-04 20:52:15 · 577 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 · 209 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 Offer 57 - II. 和为s的连续正数序列 滑动窗口规律
滑动窗口求解。规律:一个有序排列的数组,求两个数的和,可以考虑使用两个指针在两端,向中间移动。如果两个指针的和大于目标数,说明两下标之间的任意数与右下标数的和一定大于目标数,那么就淘汰右下标的数,即右指针向左移动一位。再进行比较,同理,如果两个指针的数之和小于目标数,就将左标向右移动一位,再进行比较。结束条件是left≥right。 如:1,3,5,6,7,8 target=10;一个有序排列的数组,求很多连续数字的和。可以使用两个指针(left,right)都从左边第一个...原创 2022-03-29 20:35:24 · 171 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 Offer 56 - I. 数组中数字出现的次数
//首先,空间复杂度1,说明不能使用map存储了。题意得知很多重复的元素,要寻找单个元素。可以使用异或运算。即使不在一起,两个相同的数进行异或运算也可以消掉。 //使用异或运算。然后把数组分为两份 //(异或得到的结果找到哪一位不为0,说明这一位两个数不一样。 //根据这一位把数组分为两份,两个只出现一次的数肯定分别位于两个数组中), //这两个数字分别在两个数组中,分别对数组进行运...原创 2022-03-27 20:27:03 · 103 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 Offer 51. 数组中的逆序对 题解
思路:使用普通的暴力解法会超时。选择使用归并算法(分治的思想)来解决这个问题。归并算法是将两个排好序的子数组中的元素进行排序。选择两个数组首部较小的一个放入新创建的数组当中。此时就能利用这个机制来实现题目要求。当后面一半数组第一个元素小于前面数组首部元素时,判断前半数组中还有多少个元素n,就是在这两个数组所有元素中,有n个数在该数前面,并且比它大。将所有n加起来,即题目中总的逆序对的数目。思路就是后一个数组中有元素要放入数组时,看看前一半数组中还有几个没有放进去。就是有几个比它大,组成逆序对。...原创 2022-03-25 22:20:24 · 138 阅读 · 0 评论 -
剑指 Offer 50. 第一个只出现一次的字符 题解
简单题,耗时10min。想要找到第一个只出现一次的字符,第一次遍历的时候肯定不知道后面有没有这个字符,所以首先遍历一次后,得到每个字符出现的次数,题目中给了限制:所有字符都是小写英文字母。只有26个。可以使用一个长26的数组来储存每个字符出现的次数。因为要得到第一个出现的字符,那么第二次循环从前到后读取字符,拿到它存储在数组中的出现次数。如果为1,那么返回这个字符。如果循环结束后都没有符合条件的,就说明找不到,返回一个空格字符。class Solution { public cha原创 2022-03-25 20:19:59 · 58 阅读 · 0 评论 -
剑指 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 · 71 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 Offer 48. 最长不含重复字符的子字符串 思路题解
思路:最初的思路是创建一个map,一个maxSon(int),循环将每一位字符与其下标存进去。存入之前判断这一个字符是否已经存在表中。如果不存在就直接加入,存在的话获取已经存在的该字符其下标t,可计算当前最大不重复字符串长度,与max作比较后取较大值maxSon。 之后把循环的下标移到t,清空集合map。下一循环就重新计数了。这个方法比较笨。可以选择不清空集合map,通过下标的计算来实现 动态规划的思路。新加一个临时变量max,用于表示当前最大的无重复字符串长度...原创 2022-03-24 12:19:35 · 287 阅读 · 0 评论 -
剑指 Offer 35. 复杂链表的复制 思路与代码
思路:这一题最开始没想出来,想了很久都觉得很复杂。看了答案有两个方法:1.使用递归和哈希表,创建一个哈希表,key为原链表中的元素,value为复制链表中的元素。递归判断,是否存在key。如果存在key 就说明已经创建了该复制节点,拿到复制节点。如果不存在key,说明没有创建该复制节点,应该new一个节点,next 和random都调用递归方法拿到。最终拿到的headcopy就是满足题意的。2.第二个方法使用复制双节点的方法,很巧妙。需要遍历三次:首先第一次遍历,把链表每一...原创 2021-11-27 22:32:39 · 4013 阅读 · 0 评论 -
剑指 Offer 32 - III. 从上到下打印二叉树 III 思路与代码
思路:需要将奇数行正序输出,偶数行倒叙输出。可以使用双端队列,双端队列可以控制加入与移除的是第一个还是最后一个。因此我们可以加入一个count,每次循环便加1,用来判断这一层是奇数还是偶数。如果为奇数,那么就将每一个数据加入到双端队列的最后面。得到的为正序。如果为偶数,那么将每一个数据加入到双端队列的最前面,得到的为倒序。这样就完成了树的正序与倒序的输出。还可以控制que那一个双端队列的API,实现这个功能。也可以正常输出,在加入到list前判断...原创 2021-11-24 22:13:44 · 337 阅读 · 0 评论 -
剑指 Offer 29. 顺时针打印矩阵 思路与代码
思路:首先可以明确需要输出多少个数是知道的。也就是行数*列数。我的思路是定义四种状态,上下左右。同时定义四个边界。让一个指针在边界围成的空间中按照四种状态移动。每次移动到边界,改变其状态,同时移动边界。直到输出结束。思路和代码都比较简单另外还可以使用画框的方式:大框走一圈,把边界往中间移一圈。此时开始的坐标为原坐标的右下位置。同样也需要有边界限制。可以通过判断起点是否位于边界之外判断是否循环结束。class Solution { ...原创 2021-11-22 22:53:22 · 188 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指 Offer 27. 二叉树的镜像 代码与思路
思路:看到树,第一时间要想到递归。使用递归的方法,前序遍历,把每一个节点的左右子树都进行交换。最后拿到的根节点就是所需要的树。 还可以使用栈的方法,遍历存储所有节点,再弹出交换所有节点的左右子树。/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeN...原创 2021-11-21 20:53:27 · 193 阅读 · 0 评论 -
剑指 Offer 26. 树的子结构 思路与代码
思路:由题意可知,我们需要判断树B是不是树A的子树。不管怎么样,肯定要在树A中找到与B树根节点val值相等的节点。可以选择递归或者非递归的遍历。找到节点值与树B根节点val值相等的节点。进入compare递归判断它们的结构是不是相等的(注意:在递归时如果某次递归B节点为空,那么不管A是不是空,肯定返回true。如果B节点不为空,判断如果A节点为空,那么肯定返回false。两个都不为空的情况下,判断两节点的值是不是相等的,如果是相等的,继续左节点、右节点调用compare递归...原创 2021-11-18 22:23:05 · 318 阅读 · 0 评论 -
剑指 Offer 25. 合并两个排序的链表 思路和代码
思路: 新建一个链表头结点。两个指针分别在两个链表头部,比较哪一个小。把小节点放到新的空 头结点下一位。然后新链表与小的节点所在的链表的指针都向后移一位。再次比较。直到某一个链表到尾部。将另一个还未到头的链表的指针所在节点直接接到新链表尾部。 这里我原先是遍历加入的,后来看到可以直接把剩余链表的尾部直接接到新链表尾部。这个方法更好! 最后返回新链表头结点的next节点即可。/** * Definition for singly-linked list....原创 2021-11-18 21:38:04 · 399 阅读 · 0 评论 -
剑指 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 阅读 · 0 评论 -
剑指offer 21 调整数组顺序使奇数位于偶数前面 思路与代码
思路:数组前面和后面属性不一样,前面是奇数,后面是偶数,可以想到利用两个指针前后进行判断和交换。保证左指针的左边一定是奇数,右指针的右边一定是偶数。结束条件就是两个指针相遇。代码如下:class Solution { public int[] exchange(int[] nums) { if(nums==null || nums.length==0){ return nums; } //奇数在前面 偶数...原创 2021-11-17 22:15:03 · 56 阅读 · 0 评论 -
剑指 Offer 18. 删除链表的节点 思路与代码
思路:使用一个或者两个指针定位,检测head节点val是否等于value,如果等于就直接返回head.next。检测指针的下一个节点val值是不是等于val,倘若等于,就另指针的下一个元素指向下下个元素(可能为null,不影响),此时返回head节点即可。 循环到结束没找到符合条件的节点,也直接返回head即可。注意:假如题中给的不是val值,而是要删除的节点,则判断节点的next是不是null,如果是null。从head开始遍历,找到这个节点的上个节点,令其next=...原创 2021-11-08 21:57:14 · 190 阅读 · 0 评论 -
剑指 Offer 16. 数值的整数次方 思路和代码
思路:首先,使用循环乘法的方式肯定太慢了。可以使用二分的思路大大缩短运算成本。 需要考虑x==0,n<0的情况,可以选择递归的方法与循环的方法递归的方法:如果一个数的指数是偶数,那么二分的之后,就是两个数相乘。如果它的指数是奇数,则两个数相乘后还要乘上x。class Solution { public double myPow(double x, int n) {//搞一个递归回溯运算更快// 8 -- 4 4 // 9 -- 4 4 1...原创 2021-11-08 21:02:21 · 55 阅读 · 0 评论 -
剑指 Offer 15. 二进制中1的个数
思路:这种题应该首先想到使用位运算,位运算的运算速度相当快。我的思路是使用一个1不断地左移,不断地与目标数或运算。如果结果数不变,说明这一位原本为1,计数count++,如果结果数变了,说明这一位原本为0。执行32次,就可以把int类型数全部算完。一个更好地思路:把n减1 与原来的数并运算。看结果是不是为0;如果不为0 说明前面还有1,计数count++。一直执行while循环 计算后值为0停止循环。count为所需要的数。 2的幂也可以使用这个方法算,...原创 2021-11-07 22:56:01 · 50 阅读 · 0 评论 -
剑指 Offer 14- I. 剪绳子 思路和代码
找规律如下; 可以看到从5开始就有规律了。某个数减去3 如果结果大于或等于2,就减,否则就别减了。可以根据找到的规律很容易地写出代码。2 1 13 1 24 2 25 236 337 348 332class Solution { public int cuttingR...原创 2021-11-07 22:02:24 · 52 阅读 · 0 评论 -
剑指offer 12 矩阵中的路径 思路及代码
思路:这是一个典型的二维迷宫问题,首先应该想到的是使用递归回溯的方法去找到正确的路径。首先确定测试用例,(空字符串,字符串长度为0,空数组,数组长度为0,矩阵里面包含字符串,不包含字符串)。看到题目要求判断是否包含字符串。首先需要循环遍历找到矩阵中字符与字符串中首位相等的元素下标。进入方法进行递归回溯查找。个人感觉类似于深度遍历的过程。最需要注意的是需要避免来回判断,比如{a,a} “aaa” 如果没有考虑到的话很容易导致回头判断的情...原创 2021-11-07 21:10:08 · 58 阅读 · 0 评论 -
剑指 Offer 30. 包含min函数的栈 思路分析和代码
思路如下: 题中要求min、push、和pop的时间复杂度都要为O(1),就不能使用遍历找出最小值了。所以需要想办法在加入元素的时候记录min。因为不知道存入多少个,还需要搞一个数组扩容命令。 我最初的代码是计划使用一个数组动态规划的形式记录每一位的min值,新加入的时候与min【temp-1】比较,如果比它小 min【temp】=arr【temp】,否则min【temp】=arr【temp-1】. 后来发现题解中有一个更加聪明的记录方法。使用主栈A&...原创 2021-11-01 21:47:37 · 84 阅读 · 0 评论 -
剑指offer06 从尾到头打印链表 思路及代码
想到了两个方法原创 2021-11-01 21:31:21 · 53 阅读 · 0 评论 -
剑指offer 09 两个栈实现队列 解题思路与代码
剑指 Offer 09. 用两个栈实现队列难度简单342收藏分享切换为英文接收动态反馈用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead操作返回 -1 )示例 1:输入:["CQueue","appendTail","deleteHead","deleteHead"][[],[3],[],[]]输出:[null,null,...原创 2021-10-28 22:09:25 · 58 阅读 · 0 评论 -
剑指offer07 重建二叉树思路与代码
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。示例 1:Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]Output: [3,9,20,null,null,15,7]示例 2:Input: preorder = [-1], inorder = [-1]Output: [-1]来源:力扣(LeetCode)...原创 2021-10-28 21:47:17 · 66 阅读 · 0 评论 -
单向链表构建的栈和字符串计算器代码
栈:public class StackAsLinked<TT> { int size=10; Node1 back; Node1 fanhui; Node1 n0=new Node1 ( null ); int count=0; public static void main ( String[] args ) { StackAsLinked s2 = new StackAsLinked (); Scan原创 2021-09-29 22:41:22 · 74 阅读 · 0 评论