![](https://img-blog.csdnimg.cn/20201014180756923.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offer
growthmindset
这个作者很懒,什么都没留下…
展开
-
丑数
通俗易懂的解释:首先从丑数的定义我们知道,一个丑数的因子只有2,3,5,那么丑数p = 2 ^ x * 3 ^ y * 5 ^ z,换句话说一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到,那么我们从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10,6,9,15,10,15,25九个丑数,我们发现这种方***得到重复的丑数,而且我们题目要求第N个丑数,这样的方法得到的丑数也是无序的。那么我们可以维护三个队列:(1)丑数数组: 1乘以2的队列:2原创 2020-09-22 17:08:17 · 174 阅读 · 0 评论 -
机器人的运动范围
题目描述地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?回朔法public class Solution { int count=0; public int movingCount(int th原创 2020-09-08 09:52:36 · 106 阅读 · 0 评论 -
最小的K个数
题目描述输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。思路:直接排序来做时间复杂度是nlog(n)考虑开辟一个额外的空间,空间大小为k,在遍历数小于等于k时,直接将其加到额外空间中;在遍历数大于等于k时,就要考虑额外空间中最大数是否大于当前遍历的数,若大于,则当前遍历的数替换它;若小于,则不做额外操作。考虑到每一次都要从额外数组中获取最大值,显然使用大顶堆合适,其获取操作o(1),插入删除操作o(logn)因此总的时间复杂原创 2020-09-02 14:33:14 · 121 阅读 · 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.思路:本题有多个边界值、循环,很容易出错,一定要先理清思路,画图辅助理解.每一轮大循环都会执行四个小循环(按序:向右、向下、向左、向上)并且发现它们之间存在着很大地联系:例:在向下遍历时,固定列值不变,而其列值即为本轮大循环的原创 2020-08-30 15:09:36 · 87 阅读 · 0 评论 -
和为S的连续正数序列
题目描述小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!输出描述:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序import java.util.ArrayList;原创 2020-08-03 08:17:24 · 94 阅读 · 0 评论 -
把数组排成最小的数
题目描述输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。思路:暴力解法就是对所有的排列种类进行比较,这样的复杂度为n!其实我们可以将这个大问题转化为一个个小问题,若对两个数做连接操作,所得结果大的连接顺序表明,该顺序中的第一个连接数应该排在第二个连接数之前,这样,可以对整个连接数数组做一遍快排,就能确定连接数排列顺序最优解,复杂度只要nlogn。考虑到连接数都是int类型原创 2020-07-30 16:24:27 · 118 阅读 · 0 评论 -
连续子数组的最大和
题目描述HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)思路1:若遍历位置之前求得的和sum已小于零,则没必要在它原创 2020-07-30 16:24:19 · 81 阅读 · 0 评论 -
数字在排序数组中出现的次数
题目描述统计一个数字在排序数组中出现的次数。public class Solution { public int GetNumberOfK(int [] array , int k) { int len=array.length; int l=0,r=len-1; int num=0; while(l<=r){ int mid=l+(r-l)/2; if(k>array[mid]){原创 2020-07-27 16:25:38 · 99 阅读 · 0 评论 -
数组中只出现一次的数字
题目描述一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。容易想到的思路1:可以以数字为键,数字出现的次数为值建立hash表,返回只出现一次的数。容易想到的思路2:可以先排序整个数组,当一个数与前后都不同的时候就是只出现一次的数。public class Solution { public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) { Arrays.so原创 2020-07-27 16:00:58 · 120 阅读 · 0 评论 -
左旋转字符串
题目描述汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!思路:翻转两次循环左移k位必然会将字符串分成两部分,前半部分(即:k%n个字符数)与后半部分。第一次:将字符串分成前后两部分,分别翻转;第二次:将整个字符串翻转.实质同:先整体翻转再局部翻转.pub原创 2020-07-16 10:43:27 · 95 阅读 · 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决定去买体育彩票啦。 现原创 2020-07-15 11:17:24 · 157 阅读 · 0 评论 -
平衡二叉树
题目描述输入一棵二叉树,判断该二叉树是否是平衡二叉树。在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树错误做法,对平衡二叉树的理解出现了偏差,平衡二叉树判断其是否平衡,是判断每个中间节点的左右子树高度差是否小于等于1,而不是对所有叶子节点的位置作比较.public class Solution { int max_depth=-1,min_depth=10000; public boolean IsBalanced_Solution(TreeNode root) {原创 2020-07-15 10:05:04 · 217 阅读 · 1 评论 -
序列化二叉树
题目描述请实现两个函数,分别用来序列化和反序列化二叉树二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己原创 2020-07-15 09:12:34 · 206 阅读 · 0 评论 -
二叉搜索树的第k个节点
题目描述给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。import java.util.ArrayList;public class Solution { ArrayList<TreeNode> al=new ArrayList<>(); TreeNode KthNode(TreeNode pRoot, int k){ if(pRoot==null||k<原创 2020-07-13 21:43:59 · 120 阅读 · 0 评论 -
按之字形顺序打印二叉树
题目描述请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。思路1:先全都存储在一个临时列表中,并记录每层个数,再根据层数奇偶性确定从左往右放还是从右往左放.但是:在海量数据时,这样效率太低了。public class Solution { public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {原创 2020-07-13 11:22:42 · 115 阅读 · 0 评论 -
对称的二叉树
题目描述请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。求镜像时要注意,不能简单通过将pRoot赋值给一个新的结点,然后通过新的结点获取镜像,因为这样会使得原来的二叉树也变为了它的镜像.public class Solution { boolean isSymmetrical(TreeNode pRoot) { if(pRoot==null)return true;//注意点:当根为空时也任务是对称的原创 2020-07-12 10:58:11 · 148 阅读 · 0 评论 -
二叉树中和为某一值的路径
题目描述输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。import java.util.ArrayList;import java.util.Stack;public class Solution { ArrayList<ArrayList<Integer>> res=new ArrayList<>(); int sum=0; St原创 2020-07-12 10:20:40 · 124 阅读 · 0 评论 -
从上往下打印二叉树
题目描述从上往下打印出二叉树的每个节点,同层节点从左至右打印。由于本题要求所有结点都按序存放在一个集合中,而不是每层结点分开放,因此无法使用递归来做。可以通过队列,并且本题用队列做也无需记录当前遍历层结点数以及下一层结点数。import java.util.ArrayList;import java.util.ArrayDeque;public class Solution { public ArrayList<Integer> PrintFromTopToBottom(Tr原创 2020-07-01 08:54:13 · 113 阅读 · 0 评论 -
树的子结构
题目描述输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)思路:1、通过递归遍历树A,寻找与树B中根结点的val值相等的结点;2、分别遍历A、B,判断二者结构是否相等,若相等,则结束循环返回true;若不等,则继续遍历树A,寻找与树B中根结点的val值相等的结点.public class Solution { public boolean HasSubtree(TreeNode root1,TreeNode root2) { if(r原创 2020-06-30 09:02:07 · 106 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
题目描述输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。思路:BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两段(子树)都是合法的后序序列。完美的递归定义。public class Solution { public boolean VerifySquenceO原创 2020-06-30 08:32:47 · 177 阅读 · 0 评论 -
栈的压入、弹出序列
题目描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)思路:建立一个辅助栈.import java.util.Stack;public class Solution { public boolean IsPopOrder(int [] p原创 2020-06-27 09:29:38 · 147 阅读 · 0 评论 -
复杂链表的复制
题目描述输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)思路1:哈希产生O(n)的空间,时间也是)(n),以空间换时间.import java.util.HashMap;public class Solution { public RandomListNode Clone(RandomListNode pH原创 2020-06-27 09:00:40 · 127 阅读 · 0 评论 -
二叉搜索树与双向链表
题目描述输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。解题思路:中序遍历即可。只需要记录一个pre指针即可。出现问题,middle(cur.left,pre); //会使得开始时的pre依旧保持nullpublic class Solution { public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree==null)return null原创 2020-06-25 10:39:59 · 149 阅读 · 0 评论 -
链表中倒数第k个结点
题目描述输入一个链表,输出该链表中倒数第k个结点。首先定义两个指向链表头的指针p ,q;先令一个指针指向第k节点,然后两个指针同时向后移动,最后q指向的即为倒数第k个节点。若i<k则说明k大于链表结点个数.public class Solution { public ListNode FindKthToTail(ListNode head,int k) { ListNode p=head,q=head; int i=0; for(;p!=n原创 2020-06-18 10:04:11 · 99 阅读 · 0 评论 -
合并两个排序的链表
题目描述输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。递归:public class Solution { public ListNode Merge(ListNode list1,ListNode list2) { if(list1==null)return list2; if(list2==null)return list1; if(list1.val<=list2.val){原创 2020-06-18 09:38:42 · 103 阅读 · 0 评论 -
两个链表的第一个公共结点
题目描述输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)思路:需计算链表长度首先计算两个链表长度差值,让较长者先走完差值部分,再两个链表一起往下走.public class Solution { public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { int len1=0,len2=0; Li原创 2020-06-16 10:46:33 · 153 阅读 · 0 评论 -
反转链表
题目描述输入一个链表,反转链表后,输出新链表的表头。栈:public class Solution { public ListNode ReverseList(ListNode head) { if(head==null||head.next==null)return head; ListNode pre=head,now=head.next; while(now!=null){ pre.next=now.next;原创 2020-06-15 10:06:52 · 103 阅读 · 0 评论 -
约瑟夫法——孩子们的游戏(圆圈中最后剩下的数)
题目描述每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得原创 2020-06-13 10:22:02 · 1000 阅读 · 0 评论 -
把二叉树打印成多行
题目描述从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。层次遍历import java.util.ArrayList;import java.util.ArrayDeque;public class Solution { ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> all=new Arr原创 2020-06-12 11:54:56 · 95 阅读 · 0 评论 -
二叉树的镜像
题目描述操作给定的二叉树,将其变换为源二叉树的镜像。输入描述:思路:抓住本质,获得二叉树的镜像,实质是交换每个根结点的左右子树.可用递归:循环体:交换左右子树终止条件:根结点为空/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val;原创 2020-06-12 10:33:48 · 104 阅读 · 0 评论 -
和为S的两个数字
题目描述输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。输出描述:对应每个测试案例,输出两个数,小的先输出。//输出两个数的乘积最小的。这句话的理解?假设:若b>a,且存在,a + b = s;(a - m ) + (b + m) = s则:(a - m )(b + m)=ab - (b-a)m - m*m < ab;说明外层的乘积更小也就是说依然是左右夹逼法!!!只需要2个指针1.left开头,原创 2020-06-12 10:25:04 · 104 阅读 · 0 评论 -
剪绳子
题目描述给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。输入描述:输入一个数n,意义见题面。(2 <= n <= 60)输出描述:输出答案。示例1输入8输出18题目分析:先举几个例子,可以看出规律来。4 : 225 :转载 2020-06-12 09:58:41 · 146 阅读 · 0 评论 -
整数中1出现的次数(从1到n整数中1出现的次数)
题目描述求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。思路1:设N = abcde ,其中abcde分别为十进制中各位上的数字。如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字转载 2020-06-10 09:12:35 · 223 阅读 · 0 评论 -
二叉树的深度
题目描述输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。思路1:广度优先遍历(层次遍历)使用队列存放结点,通过变量记录当前层结点数,下一层结点数,以及当前层已遍历结点数,以此来获知树的深度depth。注意点:虽然用的是队列ArrayDeque,且其包含pop(),push()方法,但它们遵照的依旧是栈思想。因此,要想使用队列的先进先出思想,可使用add()/addLast(),pollFirst()方法./**public原创 2020-06-03 08:21:32 · 123 阅读 · 0 评论 -
二叉树的下一个结点
题目描述给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路:首先通过next指针找到二叉树的根结点,再利用根结点作中序遍历,获得中序遍历的结点列表,最后通过遍历列表找到所给结点的中序遍历下一结点。需注意的是:边界情况,所给结点可能是中序遍历的尾结点,这种情况其下一结点为null./*public class TreeLinkNode { int val; TreeLinkNode left =原创 2020-05-31 09:05:04 · 294 阅读 · 0 评论 -
重建二叉树
题目描述输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。递归思路:重在递归出口与递归体/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode原创 2020-05-31 08:12:28 · 110 阅读 · 0 评论 -
滑动窗口的最大值
题目描述给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,原创 2020-05-28 11:55:39 · 159 阅读 · 0 评论 -
用两个栈实现队列
题目描述用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。思路:每次做出队操作,都将栈1中数据压入栈2,再将栈顶数据出栈用于输出,最后将栈2中数据压入栈1.import java.util.Stack;public class Solution { Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<原创 2020-05-28 10:31:18 · 223 阅读 · 0 评论 -
删除链表中重复的结点
题目描述在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5思路1、连续结点重复:1->2->3->3->4->4->52、头部结点重复:1->1->1->2->33、尾部结点重复:1->2->3->3->3注意事项:由于存在链表头结点重复情况,原创 2020-05-24 07:25:15 · 142 阅读 · 0 评论 -
从尾到头打印链表
题目描述输入一个链表,按链表从尾到头的顺序返回一个ArrayList。链表反转本地ide可用,牛客平台报错…请大佬们帮忙指错/*** public class ListNode {* int val;* ListNode next = null;** ListNode(int val) {* this.val = val;* }* }**/import java.util.ArrayLis原创 2020-05-23 08:52:51 · 101 阅读 · 0 评论