
剑指offer
每天刷一道题,并且进行总结
ohana!
欧哈纳!
展开
-
Day01:笔试题总结
一,选择题1.解析:A.Character属于是char(字符类型)的包装类B.String就是用来存放字符串的,而且是存放字符串常量的(不可变性,从String远吗来看,创建一个字符串常量的方法是用字符数组,并且被final修饰,因此是不可变的)C.StringBuffer存放字符串常量需要new一个对象,并且是存放字符串变量的(这个方法可以直接在原有的字符串后面进行拼接,不用重新创建一个对象)D.Vector是一个集合框架,不能直接存放字符串常量2.解析:从.原创 2022-02-25 16:11:38 · 434 阅读 · 0 评论 -
Day03:笔试题总结
目录一,选择题二,编程题1.字符串中展出连续最长的的数字串2.数组中出现次数超过一半的数字一,选择题1.解析:1)对于父类的成员变量来说是私有的(private),在子类中无法调用2)在同一个类中不能有两个public修饰的类(内部类除外,内部类是作为外部类的一个成员而存在)2.解析:父类没有无参的构造方法,子类在创建对象时就会默认调用super,调用父类的无参构造方法,所以就会报错3.解析:B.构造方法可以重载,可以有无参的,..原创 2022-02-27 12:10:19 · 803 阅读 · 0 评论 -
Day02:笔试题总结
目录一,选择题二,编程题1.排序子序列2.倒置字符串一,选择题1.解析:父类new子类对象都可以2.解析:可以从String方法toLowerCase的源码看这个方法的返回值代表,如果常量池中有就会返回常量池中的这个方法的返回值代表,如果常量池中没有的话,就会new一个新的字符串放进去因此,从这道题来看,在原本的字符串常量池中有“admin”,但是没有"Admin",在进行转换时,就会执行new一个新的admin出来,所以,两个字.原创 2022-02-26 20:50:34 · 847 阅读 · 0 评论 -
数组做题总结
一,二分查找class Solution { public int search(int[] nums, int target) { if(target < nums[0] || target > nums[nums.length - 1]){ return -1; } //左闭右开 int left = 0; int right = nums.length;原创 2022-04-18 09:39:59 · 708 阅读 · 0 评论 -
统计回文oj
目录一,题目内容二,解题分析三,解题代码一,题目内容二,解题分析主要在于如何将一个字符插入进字符串,在StringBuilder中有一个insert方法,可以在0到小于等于字符串长度的任意位置插入 判断是否是回文,就可以用最好理解的双向遍历完成三,解题代码import java.util.*;public class Main{ public static boolean reverse(StringBuilder str){ .原创 2022-03-13 13:18:24 · 694 阅读 · 0 评论 -
进制转换oj
目录一,题目描述二,解题分析三,解题代码一,题目描述二,解题分析十进制数的进制转换使用辗转相除法获取每步的余数;这里需要考虑几种情况:1.十进制数为负数时,这个时候就需要将十进制数转换成一个整数进行转换,只不过在最后输出的时候在结果加上一个负号就好了2.输出的值不止是阿拉伯数字,还有A-F,可以使用一个数组保存,对余数进行判断就好了;3.辗转相除得到的结果最后输出需要反序,因为计算的结果是反的;(我是保存在字符串的情况)三,解题代码import ja原创 2022-03-13 09:46:58 · 2970 阅读 · 0 评论 -
最大的礼物价值
题目内容:解题代码:class Solution { public int maxValue(int[][] grid) { /* 1.对于这道题来讲,本质上就是寻找二维数组路径最大和 2.起点只能是grid[0][0],终点只能是grid[m - 1][n - 1](就以本题来说的m和n,意思一样) 3.对于每走的一格来说,这一步要么是上面或者左面来的 4.针对于本题条件,我们从不断更新每个位置元素最大和原创 2022-01-15 13:09:09 · 4493 阅读 · 0 评论 -
旋转最小数组(重复元素)
题目:解题代码:class Solution { public int minArray(int[] numbers) { //基本思路就是先二分,后线性 int i = 0; int j = numbers.length - 1; //确定二分条件确保不越界 while(i < j){ //定义中点元素 int m = (i + j) / 2; .原创 2022-01-11 13:50:06 · 380 阅读 · 0 评论 -
数组oj --->二维数组中的查找
题目内容:分析:首先题目中有个最重要的信息,从上到下依次增大,从左到右依次增大 对于任意一个数组类型的题目,暴力法基本都可以提供一部分解法,但,暴力法很可能不是最优解,所以,这道题目是寻找一个元素,当然可以暴力遍历 再来说说优化解法,根据所给二维数组的特性,我们可以从此入手 记录左下角的元素为flag,即标志数,若target > flag,说明肯定不在flag所在的这一列,反之,那么肯定就不在flag所在的这一行解题代码:class Solution { pu原创 2022-01-11 11:33:15 · 417 阅读 · 0 评论 -
根据一个数组,判断是否是二叉搜索树的后序遍历序列
题目内容:分析:先从二叉搜索树入手什么是二叉搜索树?二叉搜索树的特点又是什么?首先,关于根结点,左子树的值域全都小于根结点,右子树的值域全都大于根结点,当以其中一个结点看做是根结点,依然满足。其次,二叉树搜索树的中序遍历结果是有序的并且递增在讨论后序遍历(主要针对于二叉搜索树)后序遍历的特点是什么?一个二叉树的后序遍历结果,其最后一个元素就是这个二叉树的根结点,如果是二叉搜索树的话,那么会有一个临界点,这个临界点左边的所有元素都小于根结点,从临界点开始,到除去最后一个元素,都是大于根节.原创 2021-12-18 21:41:06 · 1404 阅读 · 2 评论 -
最长无重复子数组
题目要求:分析:主要还是借助于顺序表的特性,可随时添加新的元素,也可以清空自己已经存放的元素的特性 两层循环遍历,一层控制遍历的起始位置,一层控制循环的从起始位置开始的整个数组,更新max,更新count,和横向扫描相类似 具体详细操作,见代码注释import java.util.*;public class Solution { /** * * @param arr int整型一维数组 the array * @return int整型原创 2021-12-15 11:30:48 · 643 阅读 · 0 评论 -
旋转数组的最小数字
题目要求:分析:一,暴力解法对于暴力解法其实也就是一次循环遍历,直到找到最小的那个数,是可以解决问题,但是,显然不符合时间复杂度的要求二,双指针法由题目可以知道,其实,旋转数组也有规律,就是两个递增数组拼接在了一起,构成了一个非递减的数组,因此,考虑使用双指针法进行遍历,对于这个题目来说,是可以的,但是,如果,运气比较差,最小的元素在最后一个位置,也就是旋转程度很深,那么时间复杂度和暴力解法无异,因此不考虑使用三,二分查找这一个题目最理想的方式就是二分查找,...原创 2021-12-14 21:33:58 · 1140 阅读 · 0 评论 -
连续子数组的最大和
题目内容:解题思路:最重要的一点 ----更新,不管利用那种方法,都需要不断的更新 我选择的解法是,不断地更新max和nums[i] 更新nums[i]的目的也很明确,为了确定,我之前的和是否是到目前为止最大还是最小的就和nums[i]进行判断,若是num[i]比之前的和还要大,那就从nums[i]开始重新计算最大和,反之,就说明前面的和确实是最大的,就将nums[i]加上,并且更新max max的更新,也很重要,如果是加上比之前的还小,那么就不更新,反之才更新解题代码:clas原创 2021-12-12 16:07:42 · 605 阅读 · 0 评论 -
序列化二叉树(序列化和反序列化)
题目内容:解题思路:一,序列化所谓序列化就是将二叉树的每个结点按照层序遍历的结果输出,这里面也包含空节点,因为这棵二叉树,不一定是一颗完全二叉树 分析到这里序列化就变得简单多了,唯一的难点在于将树编码为单字符串(Encodesatreetoasinglestring) 因此我们借用于StringBuilder 的特性,可以利用append拼接八大类型的任一种类型,此时选择以字符串类型进行拼接 并在队头结点不等于空的时候进行其子节点的入队列操作 public ...原创 2021-12-09 16:23:58 · 1188 阅读 · 0 评论 -
二叉树oj ------>二叉树中和为某一值的路径
题目要求:解题分析:最根本的思想和找公共祖先的思想比较契合(回溯法) 这道题不同的是,需要计算路径的和,如果相等且左右子树均为空的情况下才算一个路径(如果达到target的值,但是他不是叶子结点,那么也不能算) 如果到达叶子结点,但是此时的值比target大或者小,那也不行,需要从别的子树中寻找恰好符合条件的路径,并且删除掉此时path中的最后一个不符合要求的叶子结点 在保存一个路径时,需要注意的是,这个类型为引用类型,需要new一个新的ArrayList来保存(在顺序表的构造方法中,.原创 2021-12-08 20:27:40 · 391 阅读 · 0 评论 -
链表oj(复杂链表的复制-----哈希 + 原地拆分)
题目要求:解题思路:一,哈希表复杂链表的复制就是将原链表完整无误的保存一份,就相当于ctrl + c 一样,内容,格式都不会有任何变化 借用哈希表的一一对应关系,可以原链表的每个结点复制一份,在根据原链表的next,random指向,让新链表有同样的格式class Solution { public Node copyRandomList(Node head) { //如果是空链表,直接返回空链表 if(head == null){ .原创 2021-12-08 15:07:13 · 402 阅读 · 0 评论 -
股票的最大利润
题目内容:解题思路:根据要求,我们要找的最大利润,一定要保证一个条件,在最小的时候买入,在最大的时候卖出,但是,这里面的我们并不能保证最大的一定是在最小的后面出现 因此,我们的最大最小就要进行判断(相对来说的最大最小) 这个大是在相对的范围内最大,小也是一样 当我们找到一个最小的元素时,从这个元素开始,判断后面的元素,要是比他还小,那就更新最小的,缩小区间,要是有大的,那就更新最大利润,直到找出最大的最大利润 从最开始遍历时,不断更新在一个相对区间里的bestprice(这里找出了许多原创 2021-12-04 18:28:50 · 487 阅读 · 0 评论 -
构建乘积数组
题目要求:分析:不让用除法,就排除了先将所有的元素相乘,在按位相除 不用除法,暴力的解法很容易就会超时,事实上,最后一个用例就是用来检验我们所写算法的时间复杂度的 因此参考大佬的解法,可以使用上三角和下三角的方式 仔细想想,暴力解法的根本原因就是计算重复,在上下三角的运算中,完美的避免了重复计算在下三角的计算过程中,i(当前元素)array[i]= 前一个元素 * 原数组当中当前元素的前一个元素 在计算上三角时,巧妙地利用i的前后性,将未计算进去的后半部分计算进去解题代码:原创 2021-12-04 16:44:41 · 255 阅读 · 0 评论 -
把字符串转换成整数(最详细解答)
题目要求:分析:把一个一个字符以整数的形式来进行输出,需要考虑相互转化的问题 不能使用库函数!!! 首尾会有空格(进行去空格操作,可以减少不必要的判断) 区分正负正数 结果可能会越界,题目给的是Integer类型,当超过最大范围或者小于最小范围,有不同同的结果输出 不是有效转换要和越界区分开来,当首个字符是字母时或者字符数组的长度为0时,属于无效转换需要返回0具体解题思路,代码注释全有(几乎每一行都进行了说明)class Solution { public .原创 2021-12-04 12:48:54 · 12128 阅读 · 0 评论 -
二叉搜索树oj ----->二叉搜索树与双向链表
题目内容:分析:拿到这道题,首先可以观察到转换的最大特点就是将二叉搜索树以有序的状态表达出来了,因此,必须要考虑(1)如何将其转换成有序(2)其次考虑的是,怎么才能创建一个满足题目要求的双向链表解题思路:(1)用查找,改变指向的方式完成所谓查找就是进行第一步转换的过程--->中序遍历 改变指向就是在遍历的过程将其前后指向从以前的树状结构重新指向为双向链表 给一个prev的结点记录此时遍历的前一个结点,进行上述第二步的操作 返回双向链表的头结点,本质就是中序.原创 2021-11-26 02:02:55 · 532 阅读 · 0 评论 -
哈希oj---- >只出现一次的数字
题目要求:分析:要找出只出现一次的元素,用排序时间复杂度太高,暴力解法不适用,同样处理起来不好处理,最简单的首先就是考虑用哈希表,最后,通过了解也知道,异或运算同样可以解决,并且时间复杂度也不高解题思路:Map解决将数组中的元素以key值的形式保存到Map中 遍历数组时,判断value值是否为1Set解决先将数组的第一个元素保存到Set中 遍历数组,如果有相同的不保存,并且删除Set里面相同的元素 将Set转换为数组并返回异或运算解决根绝异或运算的特性,在二进制运算原创 2021-11-23 14:07:18 · 492 阅读 · 0 评论 -
二叉树oj----->判断二叉搜索树的后序遍历序列
题目内容:分析:对于这道题还是两个弄懂什么是二叉搜索树 题目要求判断什么二叉搜索树,简而言之,在这个类型的树中,根节点的左子树(值域)都比根节点(值域)小,从递归的角度看,每个子树的左右子树也不断的满足这个特性,并且中序遍历的结果就是从小到大的 题目要求的就是判断输入的数组是不是这个二叉搜索树的后序遍历的结果解题思路:根据上面分析的特性,也就知道了利用递归,不断地判断是否满足 左子树 < 根 < 右子树就可以了 数组是后序遍历结果,那么最后一个...原创 2021-11-22 23:53:55 · 586 阅读 · 0 评论 -
二叉树oj ----->判断二叉树是否为完全二叉树
题目内容:解题思路:判断是否为完全二叉树的最重要的一点就是知道什么是完全二叉树,或者什么不是完全二叉树,比较简单的是前者 完全二叉树的简单理解:最后一层的前面的每一层结点都是满的,并且最后一层不满时,没有满的双亲结点的孩子结点必须靠左 我们借助于层序遍历(层序遍历时是不空才入队列,这次就让空也入队列) 判断时,当结点为空,就是我们判断的时候如果cur为空且队列不为空,那么一定不是完全二叉树 如果cur为空且队列也为空,那么一定是完全二叉树解题代码:class Solution原创 2021-11-16 16:30:39 · 1057 阅读 · 1 评论 -
链表oj----->合并k个有序链表
题目内容:解题思路:合并k个有序链表的本质是首先可以合并两个有序有序链表 如何合并两个有序链表:新创建一个链表(为什么不能在原有的链表上进行更改,首先,链表长度不满足,其次,当更改一个其中的一个指向时,往后的结点已经丢失) 新创建的链表的指向只根据我们的要求去进行改变的 用这个方法合并时,必然会有一个链表至少有一个结点没有指向,所以,在循环结束后,需要对还没有指向空的链表继续进行连接 返回我们定义的链表就是合并后的新链表此时,合并k个升序链表就简单多了,我们只需用考虑,怎么才能让其原创 2021-11-16 15:43:59 · 550 阅读 · 0 评论 -
二叉树oj ---->合并二叉树
题目内容:解题思路:最简单的思路之一可能就是递归了吧,我们只需用把在递归的途中,相同位置的结点进行相应的处理,一共就只有四种结果,要么都存在,要么都不存在,要么一个存在一个不存在,分好情况就可以了解题代码:class Solution { public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { if(root1 == null && root2 == null){ .原创 2021-11-15 00:11:03 · 361 阅读 · 0 评论 -
二叉树oj ----->二叉树的最近公共祖先
题目内容:解题思路:公共祖先的意思就是,离这两个结点最近的公共结点,有可能是他们的双亲,也有可能是他们双亲的双亲,所以,我们的解题思路也随之而来了,就是寻找在到达他们的路径上,有没有出现重合的结点,那么这就是他们的最近的公共祖先给一个查找路径的方法 将所到的结点,按正确的存储方式放在栈当中 进行比较,如果有相同的,就返回他,若没有就返回null解题代码:class Solution { public boolean getNode(TreeNode root,.原创 2021-11-14 13:31:26 · 469 阅读 · 0 评论 -
二叉树oj ---->递增顺序查找树
题目内容:解题思路:保存中序遍历的结果 创建一个结点,利用循环将每个中序遍历中的结果赋给新的结点,并且只用赋给右子树就可以 返回创建结点的右子树解题代码:class Solution { List<Integer> list = new ArrayList<>(); public List<Integer> vin(TreeNode root){ if(root != null){ vi原创 2021-11-11 14:30:09 · 478 阅读 · 0 评论 -
二叉树oj ----- > 二叉树的右视图
题目内容:解题思路:基本思路还是借助于层序遍历,用list接收 在每层元素在进行遍历时,我们只需接收最后 i == count - 1 元素即可解题代码:class Solution { public List<Integer> rightSideView(TreeNode root) { List<Integer> list = new ArrayList<>(); if(root == null){.原创 2021-11-10 15:02:58 · 445 阅读 · 0 评论 -
二叉树oj-----> 二叉树的锯齿形层序遍历
题目内容:解题思路:基本过程和层序遍历一样,在添加新节点的过程有所不同 我们定义一个标记,要求为锯齿形交替打印,因此,正常顺序打印,使用对列,在添加时,下一次使用栈即可,进行逆序,分为当 n % 2 != 0 时和 n % 2 == 0,两种情况 在进行逆序打印时,需要注意的是,当逆序打印时,进行的下一层结点的添加,也是逆序的,所以,我们需要进行再一次保存解题代码:class Solution { public List<List<Integer>.原创 2021-11-10 14:30:52 · 388 阅读 · 0 评论 -
二叉树oj---->对称的二叉树
题目内容:解题思路:要避免的坑:在考虑做这道题的时候,我的想法是,先将原来的树镜像一下,然后,在利用是否是相同的树来进行判断,这个应该是大多数人想到的第一个方法,方法没错,但是,问题出在将原来的树镜像一下,我们将原来的树镜像了,那原来的树就没有了,有人说保存一下,是可以,但不是基本类型那样,给一个等于号就可以复制,而是一个非常复杂的过程,因此,要考虑别的方法正确的方法之一先给一个判断是否是相同树的方法 如果这个树不为空时,调用是否是相同树方法,只不过传入的参数不是两棵树,而是原创 2021-11-06 12:06:04 · 221 阅读 · 0 评论 -
二叉树oj ----> 二叉树的构建及遍历
题目内容:解题代码:import java.util.*;public class Main{ public class TreeNode{ char value; TreeNode left; TreeNode right; public TreeNode(char value){ this.value = value; } } //给一个方法,给创.原创 2021-11-05 16:47:30 · 394 阅读 · 0 评论 -
二叉树oj ——>后序遍历(非递归)
题目要求:解题思路:后序遍历相对来说比较麻烦一些,但是基本思路没有变从根节点的左子树开始,保存每一个不为空的结点 当左子树为空时,获取栈顶元素(不是取出!!!),有可能这个结点的右子树不为空,因此判断右子树若不为空,让这个结点继续进行循环 如果为空,就遍历这个结点,并将其出栈, 当我们将上一步执行之后,发现,这个循环又回到了刚刚获取过了的这个结点,如此循环,就形成了死循环 我们的原因是因为无法得知这个结点的值有没有打印,那么就给他添加一个标记,给上一个已经遍历了的结点加上标记,并.原创 2021-11-05 16:34:54 · 285 阅读 · 0 评论 -
二叉树oj ---->中序遍历(非递归)
题目内容:解题思路:主要的思路和之前的先序遍历差不多,也是利用栈的特性,不同的地方也比较小首先遍历根节点的左子树,直到左子树为空时,遍历当前结点,中序遍历的顺序是(左子树 根节点 右子树),不能直接先遍历结点,所以,这次需要保存的是当前结点解题代码:class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> list...原创 2021-11-05 16:20:31 · 279 阅读 · 0 评论 -
二叉树oj ---->先序 or 前序遍历(非递归实现)
题目内容:解题思路:在之前刚学二叉树的时候,接触的是递归,就是用递归的方法进行的先序遍历,它的时间复杂度和空间复杂度都比较高,现在用非递归的方法,首先想到的就是用循环,至于还用什么后面分析就会知道根据二叉树的先序遍历的要求 (根节点 左子树 右子树);发现,它的关键在于如何处理左子树和右子树,如果用循环去遍历左子树,问题就在于那右子树就没办法遍历到(首先说,先遍历再后遍历,这种方法明显是不行的,举个很简单的例子,根节点的左子树一律没有右子树,当然可以,那也得保证右子树同样是没有...原创 2021-11-05 13:41:01 · 298 阅读 · 0 评论 -
字符串oj ---->字符集合
题目内容:首先是句题外话,这道题当我打开它的时候是一片空白的,我的大脑也随之一片空白,就感觉,即使这道题的解法很简单,但是,我却不知到如何下手,从哪开始写,直接敲方法?显然不可以,众所周知,只有方法的代码肯定是无法运行的(除了绝大多数进去直接由系统给出类的),所以一下子它和以往的oj题目不一样的地方有很多,有非常多的地方值得去关注什么都没有,就相当于一切是空白的,系统只会出入测试用例,而且,这个测试用例进入的方式也不同于别的oj题目,是有参数列表的,因此,难度一下子又上去了,说通俗一点就是,.原创 2021-11-04 18:16:27 · 212 阅读 · 4 评论 -
二叉树oj ----> 另一棵树的子树
题目内容:解题思路:针对这道题最好的方法就是,化整为零,逐一解决,最终归为一个问题的判断(这两棵树是否相同)首先写一个方法,用来判断两棵树是否相同,即是否为同一棵树 在原方法当中,我们将是否都为空,还是一个为空一个不为空,判断完成后,在进行新的两棵树是否为同一棵树的判断 如果不是,就进行递归,在root的左子树先寻找,如果能找到,则说明就是,反之,在右子树寻找,如果能找到,那就说明是成立的解题代码:class Solution { public boolean is原创 2021-11-04 01:41:59 · 171 阅读 · 0 评论 -
二叉树oj ----> 判断两棵树是否相同
题目要求:解题思路:判断是否都为空树 判断是否为一个为空树,另一个不为空树 两个树都不为空树的时候,先判断值是否相同,接着利用递归进行一步一步的判断,当所有条件都满足时,才会返回true,反之为false解题代码: //如果两棵树都为空 if(p == null && q == null){ return true; } //如果两棵树,一棵树为空,另一棵树不为空...原创 2021-11-04 00:58:24 · 339 阅读 · 0 评论 -
层序遍历oj
题目内容:解题思路:和层序遍历基本一样,只不过是输出由二维数组形式接收了 先考虑使用队列,它的特性是先进先出,让二叉树的根节点先入队列 在大循环当中,只需每次将便利的结点的左右子树,若不为空,就让他们入队列 在for循环当当中,进行一层结点的遍历,临界点条件就是用队列的有效元素的个数,当上一层遍历完的时候,这一层所有节点的子节点都已经入队列,所以,下次循环遍历时的个数,就刚好等于一层结点的个数class Solution { public List<Lis...原创 2021-11-02 08:36:13 · 186 阅读 · 0 评论 -
用队列实现栈oj
题目内容:解题思路:首先考虑使用两个队列,队列的特性是先入先出,而栈的是后进先出 我们给定两个队列,一个队列一直保持空,只有在进行相应操作时会存在不空的情况 当一个队列中放入了元素,当要获取栈顶元素或者进行出栈时,就让这个队列中的元素依次放入到另一个队列中,只保留最后一个元素,进行peek或者是pop操作解题代码:class MyStack { Queue<Integer> q1 = new LinkedList<>(); Queue&l原创 2021-10-29 21:45:28 · 264 阅读 · 0 评论 -
实现最小栈oj
题目内容:解题思路:首先考虑使用两个栈,一个栈压入全部元素,另一个栈存储相比之下较小的那个元素 当s2为空时,和s1一起压入元素,当不为空时,如果下一个要压入的元素小于等于s2栈顶的元素时,在压入s2 执行出栈功能时,只要s1,s2栈顶的元素不相等,只出栈s1,反之,s1,s2都出栈空时s1,s2都压入栈,是为了保证,当全部元素只有一个时,最小的就是他自己本身 如果有多个元素,s2压入的条件一定是栈顶的元素小于等于s1要压入的,从压入的这一一个元素开始,到下一个压入s2的元素之前,这个元.原创 2021-10-29 10:04:50 · 249 阅读 · 0 评论