剑指offer
腾阳山泥若
简单记录开发中遇到的问题,方便快速查找
展开
-
【剑指offer】序列化二叉树
二叉树原创 2022-06-26 19:44:44 · 199 阅读 · 0 评论 -
【剑指offer】判断是不是平衡二叉树
这题只需要在求二叉树深度的基础上扩展一下即可,下面为求二叉树深度的代码。public HashMap<TreeNode, Integer> map = new HashMap<>();public int getDepth(TreeNode root) { if (root == null) return 0; int depthLeft = getDepth(root.left) + 1; int depthRight = getDep.原创 2022-05-21 13:29:35 · 196 阅读 · 0 评论 -
【剑指offer】对称的二叉树
递归法通过两个指针同时递归遍历左右两个子树,判断当前遍历到的两个节点是否相等。如下图,需要注意的是,左右子树的遍历不是完全一样,左子树采用左右遍历,右子树采用右左遍历,这样才能判断是否为镜像。public class Solution { boolean fun(TreeNode root1, TreeNode root2) { if (root1 == null && root2 == null) return true; // 左右.原创 2022-05-18 15:14:02 · 91 阅读 · 0 评论 -
【剑指offer】二叉搜索树与双向链表
双向链表从左到右的顺序很明显就是中序遍历二叉树输出的顺序,因此核心思想就是使用中序遍历,在遍历过程中调整指针的指向。需要用到两个全局变量(递归的题目不用吝啬全局变量),curNodecurNodecurNode存储上一次访问的节点,headheadhead用来保存头节点。遍历过程中只需要用到curNodecurNodecurNode。直接套用中序遍历的模板,当curNode==null时,表明是第一个节点,此时将头节点head指向第一个节点,且将第一个节点的左指针设为null,因为它没有前驱;如果不是第.原创 2022-05-17 16:55:33 · 182 阅读 · 0 评论 -
【剑指offer】二叉树中和为某一值的路径(一)
直接对二叉树进行前序遍历,每次累加当前节点的值,如果到达叶子节点,判断当前累加和是否等于给定值,是则返回true,否则继续遍历二叉树,若找不到则返回false。import java.util.*;/* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */public class Solution { /** * @.原创 2022-05-14 13:55:46 · 303 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
由于输入的是后序遍历序列,首先我们可以确定序列的最后一个位置为根节点。由于二叉搜索树的左子树比根节点小,根节点比右子树小,因此我们需要判断根节点的左右子树是否满足该条件,关键是找到其左子树和右子树。从左开始遍历序列,找到第一个比根节点大的节点,这个节点就是左右子树的界限。 如下图的二叉搜索树,其后序遍历序列为4 7 5 11 13 12 10,序列最后一位为根节点10,从左开始往右找到第一个大于10的数,即11,那么11左边(4 7 5 )均为10的左子树,右边11 13 12为10的右子树。分别判断左子.原创 2022-05-14 13:48:04 · 243 阅读 · 0 评论 -
【剑指offer】二叉搜索树的第k个节点
利用二叉搜索树的特点,左边节点的值<中间节点的值<右边节点的值,对二叉树进行中序遍历即可。通过res保存值,count记录遍历了多少个。中序遍历是在中间输出节点,所以count在中间++public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * @param proot TreeNode类 * @param k int整型 * @return int整型.原创 2022-05-11 18:44:23 · 152 阅读 · 0 评论 -
【剑指offer】数字序列中某一位的数字
如下图所示,将字符序列按照位数分为多个区域,蓝色区域共有10个数,每个数一位,占10位,橙色区域共90个数,每个数两位,占180位,以此类推。假设输入为n,首先需要求定位n在哪个区域(通过不断减去前面的区域所占的位数求得),然后计算它对应这个区域中第几个数,假设这个数为res,最后求出它是res的第几位数,得到最终结果。import java.util.*;public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定.原创 2022-05-09 13:42:56 · 162 阅读 · 0 评论 -
【剑指offer】栈的压入、弹出序列
解题思路由于出栈序列会存在很多种可能,例如入栈顺序为1,2,3,4,5,可能的出栈序列为1,2,3,4,5,4,5,3,2,1等等,不可能将所有序列进行穷举,因此需要按照入栈序列和出栈序列进行模拟,看能否在给定入栈序列下得到出栈序列,可以则成功,否则失败。通过两个指针分别遍历入栈序列pushA和出栈序列popA,如果栈顶元素等于当前出栈元素,则模拟出栈,popA后移一位,否则继续入栈,pushA后移一位,若最终栈为空则表示成功,否则失败。public boolean IsPopOrder(int[].原创 2022-05-08 13:55:29 · 1195 阅读 · 0 评论 -
【剑指offer】删除链表的节点
遍历链表,判断当前节点是否为给定删除值,是则将其删除(让该节点的父节点指向其子节点)。实现时可以在链表头部加一个临时节点,方便处理待删节点在第一个的情况。public ListNode deleteNode(ListNode head, int val) { // write code here if (head == null) return head; ListNode res = new ListNode(-1); res.next = head;.原创 2022-05-07 18:31:09 · 275 阅读 · 0 评论 -
【剑指offer】数组中重复的数字
解法1——重排序法抓住题目中的特点,由于数组的所有数字都在0~n-1范围内,所以数据的范围和下标的范围是一样的。线性扫描数组,将扫描到的数放到它对应的下标位置上。若对应位置上已经有这个数则可以判断这是一个重复的数,否则进行交换,然后继续扫描。例如对数组2,3,1,2,循环下标i=0,扫描第一个数2,将其放到下标为2的位置上,此时下标为2的位置是1,则将其与1交换得到1,3,2,2;继续从1开始(i=0,因为num[i]!=i),将1放到下标为1的位置上,此时下标为1的位置是3,则将其与3交换得到3.原创 2022-05-07 14:13:56 · 111 阅读 · 0 评论 -
【二叉树】剑指offer 78 把二叉树打印成多行
描述给定一个节点数为 n 二叉树,要求从上到下按层打印二叉树的 val 值,同一层结点从左至右输出,每一层输出一行,将输出的结果存放到一个二维数组中返回。例如:给定的二叉树是{1,2,3,#,#,4,5}该二叉树多行打印层序遍历的结果是[ [1], [2,3], [4,5] ]题解该题为二叉树的层序遍历问题,不过需要分层,分层区别与不分层的难点在于使用一个队列时需要区分两层的节点,最简单的想法是用两个队列,其中一个队列临时存储当前层的节点。而优化解法只需要一个队列,可以通过一个临时变量存储原创 2021-10-31 19:41:32 · 4003 阅读 · 0 评论 -
【二叉树】剑指offer 8 二叉树的下一个结点
描述给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示题解这题需要对各种情况分类讨论,一共有三种情况第一种:如果这个节点的右孩子不为空,根据中序遍历的特点,它的下一个节点是它的右孩子的最左边的孩子第二种:如果这个节点是其父亲的左孩子,根据中序遍历的特点,它的下一个节点就是其父亲(注意如果父亲为null原创 2021-10-31 19:18:22 · 141 阅读 · 0 评论 -
【二叉树】剑指offer 77 按之字形顺序打印二叉树
描述给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)输出[[1],[3,2],[4,5]]栈解法用两个栈来存奇数层和偶数层的节点,如果当前为奇数层则先入栈左孩子再入栈右孩子,如果为偶数层则先入栈右孩子再入栈左孩子import java.util.ArrayList;import java.util.LinkedList;import java.util.Queue;import java.util.Stack;public class原创 2021-10-31 16:51:44 · 103 阅读 · 0 评论 -
【二叉树】剑指offer 54 二叉搜索树的第k个结点
描述给定一棵结点数为 n 二叉搜索树,请找出其中的第 k 小的TreeNode结点。数据范围:0≤n<=1000 \le n<=1000≤n<=100,0≤k≤1000\le k≤1000≤k≤100,树上每个结点的值满足0≤val≤1000≤val≤1000≤val≤100要求:空间复杂度 O(1),时间复杂度 O(n)例如,输入:{5,3,7,2,4,6,8},3, 输出4题解二叉搜索树的性质是左孩子小于父节点,父节点小于右孩子,则中序遍历为有序的,需要利用该条件来求解原创 2021-10-31 15:24:09 · 141 阅读 · 0 评论 -
【树】树的子结构
来自剑指offer这题有点难度,解题思想是:若B是A的子树,则子树的根节点可能为树A中的任意一个节点,因此只需要遍历树A的每个节点,判断以这个节点为根节点的树是否包含子树B,判断这个根节点是否包含子树B的方法是递归判断左右节点是否相等,若不相等则不包含子树B,若在判断的时候该根节点的树已经空了,而子树B不空,也表示不包含子树B,若子树B为空,则表明该根节点的树还有剩余的节点,包含了子树B,若两树均空,则表明刚好包含子树B。下面代码使用层序遍历遍历树A的每个节点,使用isSub函数判断以当前节点为根节.原创 2021-03-21 12:58:52 · 163 阅读 · 0 评论 -
【树】二叉树的镜像
题目描述操作给定的二叉树,将其变换为源二叉树的镜像。思路很简单,只需要递归遍历树,然后将每个节点的左右子树调换即可import java.util.*;public class Solution { public TreeNode Mirror(TreeNode pRoot) { // write code here if (pRoot != null) { TreeNode tmp = pRoot.left;原创 2021-03-21 12:39:42 · 93 阅读 · 0 评论 -
【字符串】把字符串转换成整数
题目描述将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0输入描述:输入一个字符串,包括数字字母符号,可以为空返回值描述:如果是合法的数值表达则返回该数字,否则返回0示例1输入“+2147483647”返回值2147483647示例2“1a33”返回值0这题比较简单,使用result存储结果,sign表示符号,遍历字符串,若遇到+或-,判断是否在第一位,若不是返回0,若是则设置相应的符号位,若字符为数原创 2021-03-14 12:39:12 · 503 阅读 · 0 评论 -
【字符串 递归】正则表达式匹配
题目描述请实现一个函数用来匹配包括’.‘和’*‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配示例1输入“aaa”,“a*a”返回值true首先需要弄清楚题目意思,匹配是指字符串中的所有字符要匹配整个模式串,即两个串都要匹配到尾部。思路是递归遍历字符串和模式串,判断当前字符串和模式串是否匹原创 2021-03-04 22:07:27 · 145 阅读 · 1 评论 -
【字符串】表示数值的字符串
题目描述请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。示例1输入“123.45e+6”返回值true示例2输入“1.2.3”返回值false这道题没有太多技巧,只需要使用if-else列出所有情况即可,使用两个变量can_e和can_dot表示是否能够出现这些字符,+和-只能出现在第一原创 2021-02-21 14:02:16 · 201 阅读 · 0 评论 -
【字符串】字符流中第一个不重复的字符
题目描述请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。返回值描述:如果当前字符流没有存在出现一次的字符,返回#字符。哈希法我想到的第一种方法是哈希法,用一个哈希表来存储每个字符的信息,字符作为key,value格式为min_index num,即字符最早出现的下标和它出现的次数。每次插入字符时,判断哈希表中是否包含该字符,若包含则将其原创 2021-02-19 17:51:59 · 311 阅读 · 0 评论 -
【数组】扑克牌顺子
题目描述LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现原创 2021-02-16 21:57:00 · 349 阅读 · 0 评论 -
【字符串】翻转单词顺序列
题目描述牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?示例1输入“nowcoder. a am I”返回值“I am a nowcoder.”这道题难度不高,通过空格拆分字符串得原创 2021-02-14 21:07:42 · 246 阅读 · 0 评论 -
【字符串】左旋转字符串
题目描述汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!示例1输入“abcXYZdef”,3返回值“XYZdefabc”这题难度较低,可以使用字符串截取将两部分字符串拼接在一起,例如abcXYZdef左移3位,则将XYZdef和abc拼在一起即可,注意当原创 2021-02-14 19:27:01 · 132 阅读 · 0 评论 -
【字符串】第一个只出现一次的字符
题目描述在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)输入“google”返回值4哈希法这是我第一个想到的方法,利用一个哈希表,遍历一次字符串,将字符作为哈希键值,字符的下标作为value,若字符重复出现,则将其value变成10002(最大值);最后遍历一次value的值,返回最小的下标,若最小的下标为10002,则全为重复的字符返回-1public int原创 2021-02-14 11:09:04 · 258 阅读 · 0 评论 -
【二分法】数字在升序数组中出现的次数
题目描述统计一个数字在升序数组中出现的次数。示例1输入[1,2,3,3,3,3,4,5], 3返回值4看到数组是有序的,并且是查找,应该想到用二分法,最简单的方法是用二分法找到该数,然后以它为中心向左右两边搜索计数public class Solution { public int GetNumberOfK(int[] array, int k) { // 二分查找 int low = 0, high = array.length - 1, midd原创 2021-02-12 21:08:30 · 264 阅读 · 2 评论 -
【数组】构建乘积数组
题目描述给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2];)对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。示例1输入[1,2,3,4,5]返回值[120,60,40,30,24]以原创 2021-02-12 15:43:55 · 127 阅读 · 0 评论 -
【数组】数组中重复的数字
题目描述在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。返回描述:如果数组中有重复的数字,函数返回true,否则返回false。如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)哈希法最容易想到原创 2021-02-10 17:47:11 · 358 阅读 · 0 评论 -
【数组】把数组排成最小的数
题目描述输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。先将每个数字转换成字符串,然后对字符串进行排序即可,关键是排序的时候需要重新定义两个字符串之间的比较函数,不能按最简单的字典序来比较,因为这样输出的结果并不是最小的。对于字符串a和b,可以将两者拼在一起得到ab和ba,...原创 2021-02-09 14:45:17 · 328 阅读 · 0 评论 -
【动态规划、递归回溯】字符串的排列
题目描述输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。示例输入“ab”返回值[“ab”,“ba”]动态规划动态规划的思想是将问题分解成子问题,从最小的子问题开始解,不断扩大子问题,并利用子问题的解来求解大问题,直到解出原问题。对于字符串排列,最小的子问题是单个字符,它的排列就是它本身原创 2021-02-08 17:38:22 · 334 阅读 · 0 评论 -
【动态规划】连续子数组的最大和
题目描述输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).输入:[1,-2,3,10,-4,7,2,-5]返回值:18说明:输入的数组为{1,-2,3,10,—4,7,2,一5},和最大的子数组为{3,10,一4,7,2},因此输出为该子数组的和 18。参考博客动态规划使用动态规划来求解,需要一个表格数组dp存储累加和,以及一个变量res存储最优值,从头遍历数组,即从子问题开始,不断将问题规模扩大,同时利用原创 2021-02-07 20:35:01 · 439 阅读 · 0 评论 -
【双指针】和为S的两个数字
题目描述输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。输入[1,2,4,7,11,15],15返回值[4,11]题解使用双指针,初始化指针i,j分别在数组的头和尾,当arr[i]+arr[j]<sum,说明两个数太小了,要让i++得到更大的数,相反要让j--得到更小的数,如果arr[i]+arr[j]=sum,则是需要的结果,此时比较这个结果的乘积是否更小,若更小,则更新结果import jav原创 2021-02-06 20:49:49 · 120 阅读 · 0 评论 -
【数组】数组中出现次数超过一半的数字
题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。排序法对数组进行排序,若某个数的出现次数超过数组长度的一半,那这个数肯定出现在中位数位置上,然后遍历一次数组判断这个数的出现次数是否大于数组长度的一半即可import java.util.Arrays;public class Solution { public int原创 2021-02-06 20:20:13 · 631 阅读 · 0 评论 -
【数组】顺时针打印矩阵
题目输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.题解其实就是绕着矩阵的外圈顺时针输出矩阵的值,步骤为:从最左到最右从最上到最下从最右到最左从最下到最上缩小上下左右的边界,重复步骤1因此,可以设置4个变量left,right,top,bottom来控制循环的边界,原创 2021-02-06 15:37:19 · 139 阅读 · 2 评论 -
【链表】复杂链表的复制
题目描述输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)复杂链表的定义哈希表解法由于复杂链表的节点label是唯一的,因此可以使用哈希表, 将label作为键值,node作为value,每次添加next或者random节点时先判断哈希表中是否已存在该label对应的节点,若存在,则返回该节点,若不存在则新建一个节原创 2021-02-03 21:51:26 · 362 阅读 · 0 评论 -
【链表】删除链表中的重复节点
题目描述在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5栈解法遍历链表,将不重复的节点压栈,栈底则为不重复链表的表头,每次遍历的节点与栈顶的节点比较,若相同则将栈顶节点出栈,循环找到下一个不和当前节点重复的节点,并将新的栈顶节点的下一个节点指向这个不和当前节点重复的节点。import java.util.Stack;publi原创 2021-02-02 12:01:52 · 834 阅读 · 0 评论 -
【链表】链表中环的入口结点
题目描述给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null快慢指针法求解链表中关于环的问题最常见的是使用快慢指针,fast指针和slow指针均从链表的头开始,fast一次走两步,slow一次走一步,若链表中有环,则fast指针会先进入环中,当 slow也进入环后,经过一定的步数,fast指针就会追上slow指针,因为每移动一次fast就离slow近一步。关于链表中和环有关的问题参考。要找到环的入口点首先要用快慢指针计算出环的节点个数n,然后再用两个指针,其中一个指针先走n步,原创 2021-02-01 22:18:38 · 101 阅读 · 0 评论 -
【链表】两个链表的第一个公共结点
题目描述输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)解法这题首先需要理解两个链表的公共节点的意思,如果两个链表有公共节点,说明两个链表都指向同一个节点,因为引用数据类型在堆中存储的是地址,那么相遇后就合并成一条链了。...原创 2021-02-01 11:17:13 · 98 阅读 · 0 评论 -
【反转链表】
题目输入一个链表,反转链表后,输出新链表的表头。题解遍历一遍链表,在遍历的过程中不断将指向关系反转,可以想到需要两个指针fast和slow,fast在前,slow在后,两个指针一同前进,每一次fast将其next指向slow,即反转指向关系,为了保证fast后面的所有节点不失效,还需要第3个指针tmp保存fast的下一个节点。public class Solution { public ListNode ReverseList(ListNode head) { if (he原创 2020-10-19 13:13:40 · 115 阅读 · 0 评论 -
【双指针(快慢指针)】链表中倒数第k个结点
题目输入一个链表,输出该链表中倒数第k个结点。暴力解法很多种,先遍历一遍,统计链表的长度,让后找正数的第n-k-1个节点。快慢指针使用两个指针,fast和slow,fast比slow快k步,则当fast走到尽头的时候,slow所处的位置就是倒数第k个节点所处的位置public class Solution { public ListNode FindKthToTail(ListNode head, int k) { if (k < 0) r原创 2020-10-18 23:35:44 · 233 阅读 · 0 评论