剑指OFFER思路总结与代码分享——树篇(Java实现)
剑指OFFER树相关
- 55-1 二叉树的深度
- 27 二叉树的镜像
- 54 二叉搜索树的第K大节点
- 32-II 从上到下打印二叉树
- 07 重建二叉树
- 68-I 二叉搜索树的最近公共祖先
- 68-II 二叉树的最近公共祖先
- 32-I 从上到下打印二叉树
- 32-III 从上到下下打印二叉树
- 55-II 平衡二叉树
- 28 对称的二叉树
- 34 二叉树中和为某一值的路径
- 37 序列化二叉树
- 26 树的子结构
注:顺序是先筛选分类再按LeeCode上的通过率排的,每题最后的总结代码都是在LeeCode上跑过的,应该没啥问题。但是思路中的代码都是直接在CSDN编辑器里徒手敲的,若有笔误还烦请告知,蟹蟹~
55-1 二叉树的深度
思路是使用递归,说到递归,立马写下如下思路:
- 方法想要干什么?
- 方法的终止条件是什么?以此确定终止条件;
- 方法的等价关系是什么?以此确定返回值。
立马写下如下三个词:
- 终止条件
- 递推关系
- 返回值
然后开始分析:
- 首先这个方法想要计算以入参root为根节点的树的深度,那么方法的返回值即为此树的深度;
- 其次这个方法的终止条件是当传入的root为空时,返回深度为0;
- 最后这个方法的等价关系是root节点的深度等于:root左节点的深度与root右节点的深度相较而言更大的那个深度加上1。
分析结束,将思路转为代码段在草稿纸上写:
终止条件:
if(root == null){return 0;
}
递推关系:
depth = Math.max(maxDepth(root.left).maxDepth(root.right)) + 1;
返回值:
return dpeth;
整理成代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public int maxDepth(TreeNode root) {if(root == null){return 0;}return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;}
}
27 二叉树的镜像
开始分析:
- 首先这个方法要将以入参root为根节点的树镜像变换;
- 其次当root为空的时候停止遍历,返回
null
; - 最后递归关系是将root左节点的镜像放在右节点上,将root右节点的镜像放在左节点上,即可完成root的镜像。
终止条件:
if(root == null){return null;
}
递推关系:
TreeNode tmp = root.left;
root.left = mirrorTree(root.right);
root.right = mirrorTree(tmp);
返回值:
return root;
整理成代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public TreeNode mirrorTree(TreeNode root) {if(root == null){return null;}TreeNode tmp = root.left;root.left = mirrorTree(root.right);root.right = mirrorTree(tmp);return root;}
}
54 二叉搜索树的第K大节点
开始分析:
- 首先这个方法是求第K大个节点对应的值;
- 其次当传入节点为
null
时返回,或者找到了第K大节点后返回; - 最后递归关系是使用反中序遍历的方法遍历这颗二叉搜索树,很关键的一点是看到二叉搜索树首先想到中序遍历,因为二叉搜索树的中序遍历结果是从小到大有序的数组,具体说来就是先看右子树有没有第K大,没有的话看自己是不是第K大,最后再看左子树有没有第K大。
知识点:看到二叉搜索树想到中序遍历
终止条件:
if(root == null){return;
}
if(count == 0){return;
}
递推关系:
helper(root.right);
if(--count == 0){res = root.val;
}
helper(root.left);
返回值:
//res直接写在类内上,所有方法共用,不用返回
整理成代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {private int count = 0,res = 0;public int kthLargest(TreeNode root, int k) {count = k;helper(root);return res;}private void helper(TreeNode root){if(root == null){return;}helper(root.right);if(count == 0){return;}if(--count == 0){res = root.val;}helper(root.left);}
}
32-II 从上到下打印二叉树
开始分析:
此题需要用到层次遍历,层次遍历也可以被称为二叉树的广度优先遍历BFS,说道广度优先遍历,就要想到我们需要维护一个队列,通过控制节点在队列的进出来控制遍历的节奏。
二叉树BFS的大致框架,更多细节在具体实现的代码注释中有讲到:
//初始化一个队列并把首节点放进队列里
Queue<TreeNode> queue = new LinkedList<>(){{add(root);}};
//当队列不为空的时候循环
while(!queue.isEmpty()){//一层层算账for(int i = queue.size(); i > 0; i--){//先把本层节点给poll出来TreeNode node = queue.poll();//再把与本层相连的下层左右节点给塞进去if(node.left != null){queue.add(node.left);}if(node.right != null){queue.add(node.right);}}
}
知识点:广度优先,先建队列,每层poll出,下层add进。
因为这题打印结果呈现每层单独一个ArrayList的结果,所以要在每层的循环中开一个ArrayList接一下即可。总体框架还是能看出来的。
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//判断特殊情况if(root == null){return new ArrayList<>();}//一个ArrayList承载最后的结果List<List<Integer>> res = new ArrayList<>();//一个Queue->LinkedList承载每一层的节点,初始化为首层的rootQueue<TreeNode> queue = new LinkedList<>(){{add(root);}};//若queue为空,则说明所有的节点都处理完毕,可以输出结果了//这里用queue.isEmpty(),不能用queue==nullwhile(!queue.isEmpty()){//缓存每层的数据,这里用List<Integer>是为了每层直接接上最后的结果List<Integer> tmp = new ArrayList<>();//一个for,从queue.size()开始,这很关键,//用for(int i = 0; i < queue.size(); i++)的话,则会报错//因为队列的长度是在变化的,应该首先就指定好,这样才能保证每次循环只出一层的数据for(int i = queue.size();i > 0; i--){//队列先进先出,进是add出是pollTreeNode father = queue.poll();//记得先判断是否为空再添加进队列中,不然会报空指针异常if(father.left != null){//把左孩子加入进去,等待其在下一层被poll出来queue.add(father.left);}//右孩子同理if(father.right != null){queue.add(father.right);}//把poll出的节点的值存进ArrayList中tmp.add(father.val);}//把一层的ArrayList值存进最后的结果中res.add(tmp);}return res;}
}
07 重建二叉树
先序遍历:根左右
中序遍历:左根右
1:前序遍历的首节点为root
int rootVal = preorder[0];
2:根据拿到的root去中序遍历里寻找对应的root
int rootIndex = 0;
for(int i = 0; i < inorder.length; i++){if(rootVal == inorder[i]){rootIndex = i;break;}
}
3-4:在中序遍历中找到root之后,它的左右即为当前root节点的左子树和右子树
//inorder的左边:
Arrays.copyOfRange(inorder, 0, rootIndex);
//inorder的右边:
Arrays.copyOfRange(inorder, rootIndex + 1, inorder.length);
注意copyOfRange的取值范围是左闭右开,可以画图观察,Java里很多这种取值的操作都是左闭右开的,想想str.substring(闭,开);
5-6:根据我们得到的左右子树,去前序遍历找左右子树的段落
//preorder的左边:
Arrays.copyOfRange(preorder, 1, 1 + rootIndex);
//preorder的右边:
Arrays.copyOfRange(preorder, 1 + rootIndex, preorder.length);
7-8:根据前序遍历的特点,我们所找的段落的首节点就是直接连着root的左孩子与右孩子
root.left = buildTree(preorder的左边,inorder的左边);
root.right = buildTree(preorder的右边,inorder的右边);
至此我们就可以进行递归操作了。
有没有发现树的递归操作很多时候都是在root.left和root.right的时候用等于接上的,这种格式可以多多考虑:
root.left = 递归左子树;
root.right = 递归右子树;
整理成代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public TreeNode buildTree(int[] preorder, int[] inorder) {int n = preorder.length;if(n == 0){return null;}int rootVal = preorder[0],rootIndex = 0;for(int i = 0; i < n; i++){if(rootVal == inorder[i]){rootIndex = i;break;}}TreeNode root = new TreeNode(rootVal);root.left = buildTree(Arrays.copyOfRange(preorder,1,1 + rootIndex),Arrays.copyOfRange(inorder,0,rootIndex));root.right = buildTree(Arrays.copyOfRange(preorder,1+rootIndex,n),Arrays.copyOfRange(inorder,rootIndex+1,n));return root;}
}
68-I 二叉搜索树的最近公共祖先
- 方法的作用是用来找root节点为根节点的树里指定两个节点的公共祖先;
- 当传入为
null
时返回; - 根据二叉搜索树的性质,若是p与q一个比root大一个比root小,那么就说明root在两个节点之间,否则就在根据root与p、q的大小来判断左边或者右边。
终止条件:
if(root == null){return null;
}
递推关系:
if(root.val > p.val && root.val > q.val){return lowestCommonAncestor(root.left, p, q);
}else if(root.val < p.val && root.val < q.val){return lowestCommonAncestor(root.right, p, q);
}
返回值:
return root;
整理成代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null){return null;}if(root.val > p.val && root.val > q.val){return lowestCommonAncestor(root.left, p, q);}else if(root.val < p.val && root.val < q.val){return lowestCommonAncestor(root.right, p, q);}return root;}
}
68-II 二叉树的最近公共祖先
- 方法的作用是看p或q在不在,若在则返回p或q,若不在则返回null
- 当
root == null
的时候返回null
,root == p
的时候返回p
,root == q
的时候返回q
- 当左子树为
null
说明两个都在右边,当右子树为null
说明两个都在左边,只有左右子树都不为null
的时候该root才是公共祖先,返回这个root,层层上传。
终止条件
if(root == null){return null;
}
if(root == p || root == q){return root;
}
递推关系
TreeNode leftNode = lowestCommonAncestor(root.left,p,q);
TreeNode rightNode = lowestCommonAncestor(root.right,p,q);
if(leftNode == null){return rightNode;
}
if(rightNode == null){return leftNode;
}
返回值
return root;
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null){return null;}if(root == p || root == q){return root;}TreeNode leftNode = lowestCommonAncestor(root.left,p,q);TreeNode rightNode = lowestCommonAncestor(root.right,p,q);if(leftNode == null){return rightNode;}if(rightNode == null){return leftNode;}return root;}
}
32-I 从上到下打印二叉树
这题为啥会比32-II做出来的人少…我蒙了,就是广度优先遍历的板子就完事了。
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public int[] levelOrder(TreeNode root) {//特殊边界要提前考虑到if(root == null){return new int[0];}LinkedList<TreeNode> queue = new LinkedList<>(){{add(root);}};ArrayList<Integer> res = new ArrayList<>();while(!queue.isEmpty()){for(int i = queue.size(); i > 0; i--){TreeNode tmp = queue.poll();res.add(tmp.val);if(tmp.left != null){queue.add(tmp.left);}if(tmp.right != null){queue.add(tmp.right);}}}//这里返回值是int[],再遍历一遍传过去吧,卑微int[] n = new int[res.size()];for(int j = 0; j < res.size(); j++){n[j] = res.get(j);}return n; }
}
32-III 从上到下下打印二叉树
你要是一路看下来的话这玩意是第三个BFS题了,加个reverse就完事了。这题我们来唠唠返回值的事,这个方法让我们返回的是List<List<Integer>>
这么个玩意,当root == null
的时候,我们应该怎么看返回个啥呢?答案是看它最外层是啥,它最外层是个List<>
,那我们就
if(root == null){return ArrayList<>();//return LinkedList<>();一样也行
}
这玩意说难也不难,就是有时候会一下钻牛角尖里,不造返回啥了,写出来防止忘记。
还有一个好玩的操作是判断奇偶数,这么写其实也不会快(因为听说你用取余的时候,JAVA底层已经优化成这种写法了),但是秀呀哈哈。
//奇数
if((i & 1) == 1){...
}
//偶数
if((i & 1) == 0){...
}
最后上个代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {if(root == null){return new ArrayList<>();}LinkedList<List<Integer>> res = new LinkedList<>();LinkedList<TreeNode> queue = new LinkedList<>(){{add(root);}};、//设置个层数int floor = 0;while(!queue.isEmpty()){ArrayList<Integer> tmp = new ArrayList<>();for(int i = queue.size(); i > 0; i--){TreeNode node = queue.poll();tmp.add(node.val);if(node.left != null){queue.add(node.left);}if(node.right!= null){queue.add(node.right);}}//当奇数层时需要翻转if((floor & 1) == 1){Collections.reverse(tmp);}res.add(tmp);//层数++floor++;}return res;}
}
55-II 平衡二叉树
emmm这题写的有点丑,虽然最后蜜汁跑出了99.96%和100%的成绩…
思路就是递归,感觉不用之前那么一板一眼的分析了,有点感觉了,就直接说我怎么想的吧。首先拿到左边和右边的高度,两个一减取个绝对值,要是这个值大于1呢就说明刚好在你正在处理的root节点完球了,返回false
就完事了,不然呢,就返回左子树有没有完球 && 右子树有没有完球
。还有一个问题是我们怎么知道左边和右边的高度是多少呢?再写个函数,像“55-1 二叉树的深度”那题那样递归一下就完事了。
所以我写了两个递归咋跑到99.96%的?我看大佬们写的比我简洁多了。
我好像发现了做递归题的idea:
你:算法之神,你只要告诉我前一次_______,我就能给你整出我这个________。
算法之神:小伙子牛逼哦,那我给你前一次__________的结果,你算吧。
你:现在只要把前一次_________xxxxx,然后xxxxx,最后返回的_______就是我这个________了,牛逼不。
算法之神:牛逼哦~
你:算法之神,你只要告诉我前一个节点是不是平衡二叉树,我就能给你整出我这个节点是不是平衡二叉树。
算法之神:小伙子牛逼哦,那我给你前一个节点是不是平衡二叉树的结果,你算吧。
你:现在只要看左边是不是平衡二叉树,再看右边是不是平衡二叉树,要是两边都平衡,那我这个节点就是平衡二叉树,要是有一边不是,那我这个节点就不是平衡二叉树。牛逼不。
算法之神:牛逼哦~
顺便记一下绝对值方法:
Math.abs(i);
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public boolean isBalanced(TreeNode root) {//空树肯定平衡if(root == null){return true;}//拿左右子树高度int leftNode = treeHeight(root.left);int rightNode = treeHeight(root.right);//瞅瞅自己这个节点上两个差有没有大于1,大于了就麻溜的falseif(Math.abs((leftNode - rightNode)) > 1){return false;}//瞅瞅左边,瞅瞅右边return isBalanced(root.left) && isBalanced(root.right);}public int treeHeight(TreeNode root){//空了高度就是0了if(root == null){return 0;}//左边高度和右边高度拿到int leftHeight = treeHeight(root.left);int rightHeight = treeHeight(root.right);//现在的高度就是左右高度高的那嘎达加1return Math.max(leftHeight,rightHeight) + 1;}
}
28 对称的二叉树
镜像就是左边的左边等于右边的右边,左边的右边等于右边的左边。
我们造一个递归方法,表示该树是否镜像,只要告诉我左边的左边和右边的右边是不是镜像,左边的右边和右边的左边是不是镜像,我就能告诉你当前节点是不是镜像,我只要再判断当前节点的左右是一样的即可。
判断左右节点一样之前要保证他们都不是null或者都是null,不然会报空指针,用这样的模板即可:
//先判断左右是不是都是null
if(left == null && right == null){return true;
}
//已经排除左右都是null的情况下,任意一边为null都说明left和right不相等
if(left == null || right == null){return false;
}
代码如下:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public boolean isSymmetric(TreeNode root) {if(root == null){return true;}return helper(root.left,root.right);}private boolean helper(TreeNode left,TreeNode right){if(left == null && right == null){return true;}if(left == null || right == null){return false;}//除去null,还有一种false是左右不相等if(left.val != right.val){return false;}//算法之神告诉了我左左右右和左右右左是不是镜像//如果左右相等,那本节点的结果就是 左左右右 && 左右右左 的结果return helper(left.left,right.right) && helper(left.right,right.left);}
}
34 二叉树中和为某一值的路径
这题是传说中的回溯(么?我也不知道),我死在浅拷贝还是深拷贝上了,绝望调试了半天…这地方是个深坑,没踩过十有八九是会忽略的,这题就来唠唠这玩意。
先说整体思路吧,一个List<List<Integer>>
来接最后的结果,一个List<Integer>
来接(这里插一句,看我顶上一开始申明的LinkedList<Integer>
就知道我想拿栈来做这玩意了,结果发现栈做出来结果是倒序的它不认,加个Collections.reverse()
直接给我干掉2ms,拉倒吧还是用队列做吧。),然后就是一个递归函数。
唠唠这个递归函数,首先碰到null返回,其次在本节点中的任务是先把本节点的值加在统计本条线路的值中,然后把本节点塞进队列里,再去查看本节点是不是叶子,如果是叶子的话就看和我们想要的值是否相等,相等就深拷贝一下我们记录的这条线路,然后把本节点的值减掉,把本节点吐出来;要不是叶子节点就向左向右递归,注意递归一路弹回来到这之后还是要把本节点吐出来的,所以不如直接把吐出来放在最后,少打一句话舒坦三十秒。
提一嘴这个函数,用队列的时候可以用上:
LinkedList<Integer> linkedlist = new LinkedList<>();
linkedlist.removeLast(); //删除队列的最后一个元素
先看代码再说坑,代码如下:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {List<List<Integer>> res;LinkedList<Integer> ways;int sum = 0;public List<List<Integer>> pathSum(TreeNode root, int sum) {if(root == null){return new ArrayList<>();}//前期准备res = new ArrayList<>();ways = new LinkedList<>();this.sum = sum;//调用递归方法helper(root,0);return res; }private void helper(TreeNode root,int waySum){if(root == null){return;}//本节点到了,先给他把值加上,塞队里waySum += root.val;ways.add(root.val);//瞅瞅本节点是不是叶子节点啊,是叶子的话总值对不对啊if(waySum == sum && root.left == null && root.right == null){//深拷贝的牌面还是要有的,把当前路径深拷贝到结果队列里res.add(new LinkedList<>(ways));}else{//不是叶子,下面还有节点,药不能停,向左向右继续helper(root.left,waySum);helper(root.right,waySum);}//把最后一位移除收尾,对于叶子来说是把叶子移出;//对于非叶子来说是递归结束的时候弹到本节点时把本节点移出ways.removeLast();}
}
然后就要说拷贝这事了,我一开始在叶子节点那是这么写的:
if(waySum == sum && root.left == null && root.right == null){res.add(ways);
}
然后就麻了,得到的结果是这样的:
[[],[]]
我寻思找出来路径的个数也对了啊,怎么不显示路径呢,我也add(ways)
了啊。最后发现我这样写是浅拷贝,拷贝的只是指向ways
的一个指针,所以ways
一会add(root.val)
的一会removeLast()
的,我想输出的值也在跟着变了。
浅拷贝(Shallow Copy):
①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
所以这时候要深拷贝一下,直接新建一个LinkedList<>()
然后把ways
里的值拷贝过去就完事了。
if(waySum == sum && root.left == null && root.right == null){res.add(new LinkedList<>(ways));
}
深拷贝(Deep Copy):
相对于浅拷贝而言,对于引用类型的修改,并不会影响到对应的copy对象的值。
每一层的每个对象都进行浅拷贝=深拷贝。
来做个总结:
以后出现结果个数正确、内容错误或消失的时候,可以考虑是否是浅拷贝导致的。
37 序列化二叉树
思路是用BFS做序列化和反序列化,主要还是细心,很多小细节调了不少次,还有就是Sting和Integer的转换注意下,最后注意一下String判相等还是用equals()
吧,怎么着都方便点。
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
public class Codec {// Encodes a tree to a single string.public String serialize(TreeNode root) {if(root == null){return "";}Queue<TreeNode> queue = new LinkedList<>(){{add(root);}};StringBuilder sb = new StringBuilder();sb.append("[");while(!queue.isEmpty()){for(int i = queue.size(); i > 0; --i){TreeNode tmp = queue.poll();if(tmp != null){sb.append(tmp.val + ",");queue.add(tmp.left);queue.add(tmp.right);}else{sb.append("null,");}}}sb.append("]"); return sb.toString();}// Decodes your encoded data to tree.public TreeNode deserialize(String data) {if(data == "" ){return null;}data = data.substring(1,data.length() - 1);String[] strs = data.split(",");int index = 0;TreeNode root = new TreeNode(Integer.parseInt(strs[0]));Queue<TreeNode> queue = new LinkedList<>(){{add(root);}};index++;while(!queue.isEmpty()){TreeNode node = queue.poll();if(!strs[index].equals("null")){node.left = new TreeNode(Integer.parseInt(strs[index]));queue.add(node.left);}index++;if(!strs[index].equals("null")){node.right = new TreeNode(Integer.parseInt(strs[index]));queue.add(node.right);}index++;}return root;}}// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
26 树的子结构
首先需要递归的是从本层节点开始,是否有B树的子结构,这个需要一个对比是否是子结构的递归,然后我们还需要一个递归是从本层节点的左右节点开始,是否有B树的子结构,所以这题是双重递归。
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public boolean isSubStructure(TreeNode A, TreeNode B) {if(A == null || B == null){return false;}//递归A的节点return helper(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);}//递归A某节点向下的树与B树是否一致private boolean helper(TreeNode A, TreeNode B){if(B == null){return true;}if(A == null){return false;}return A.val == B.val && helper(A.left,B.left) && helper(A.right,B.right);}
}
到此为止树的部分就结束啦~求个关注啵啵啵(●´З`●)
剑指OFFER思路总结与代码分享——树篇(Java实现)相关推荐
- 《LeetCode力扣练习》剑指 Offer 25. 合并两个排序的链表 Java
<LeetCode力扣练习>剑指 Offer 25. 合并两个排序的链表 Java 一.资源 题目: 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的. 示例1: ...
- 《LeetCode力扣练习》剑指 Offer 15. 二进制中1的个数 Java
<LeetCode力扣练习>剑指 Offer 15. 二进制中1的个数 Java 一.资源 题目: 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ...
- 《LeetCode力扣练习》剑指 Offer 09. 用两个栈实现队列 Java
<LeetCode力扣练习>剑指 Offer 09. 用两个栈实现队列 Java 一.资源 题目: 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 de ...
- 剑指offer思路与实现总结(Java版)
##节选剑指offer比较经典和巧妙的一些题目,以便复习使用.一部分题目给出了完整代码,一部分题目比较简单直接给出思路.但是不保证我说的思路都是正确的,个人对算法也不是特别在行,只不过这本书的算法多看 ...
- 剑指offer思路总结
统一格式前注: 标题对应<剑指offer>题号 时间复杂度 空间复杂度 思路:包括解题思路和编程中的技巧 教训:编程过程中需要注意的地方以及存在的惯性错误 1.赋值运算符函数(略) 2.实 ...
- java 栈和队列实现迷宫代码_LeetCode每日一题--剑指 Offer 09. 用两个栈实现队列(Java)
DailyChallenge 剑指 Offer 09. 用两个栈实现队列 Easy20200630 Description 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTai ...
- 【剑指offer】 用两个栈实现队列 java实现
[剑指offer] 用两个栈实现队列 题目: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 分析: 栈和队列的性质,栈是先进后出的,而队列是先进先出的.对于栈我 ...
- 【LeetCode笔记】剑指Offer 59. I 滑动窗口的最大值(Java、单调队列)
文章目录 题目描述 思路 && 代码 1. 暴力法 O(n2n^2n2) && O(1) 2. 单调队列辅助 O(n) && O(n) 二刷 打卡第十天 ...
- 【LeetCode笔记】剑指 Offer 03. 数组中重复的数字(Java、哈希表、原地算法)
文章目录 题目描述 思路 & 代码 二刷 题目描述 倒是和leetcode 287 寻找重复数很像..但是不能使用那道题的快慢指针法(也可能是我太菜了) 重点在于题干的描述[长度为 n 的数组 ...
最新文章
- center os7 安装mysql
- C/C++语言开源库
- 三白话经典算法系列 Shell排序实现
- 不适合的研究生,分流!不适合的导师,退出!
- 计算机毕设最快多长时间,大学几年快结束了,计算机毕设到底该怎么做?
- Bootstrap-组件-1
- winForm入门学习
- 12015.linux通过代码或命令形式操作内存/dev/mem
- 让wordpress判断是电脑端浏览还是移动端浏览
- linux自带的cpu监测工具,Linux CPU实时系统监控工具mpstat
- windows下常见php集成环境安装包介绍(updated)
- Linux ls -l 各字段解释,硬链接软连接
- python毕业设计题目推荐汽车销售系统
- 桌面图标快捷方式小箭头_如何在Windows 7、8和10中删除(或更改)快捷方式图标上的箭头...
- 解决:SpringBoot--获取自动注入属性为空失败(注解无误情况下)
- 哈佛架构 VS 冯·诺依曼架构
- 2022年车险攻略:1分钟告诉你什么是车险怎么买?
- oracle季初,Oracle获取月初/月末/季初/季末/半年初/半年末/年初/年末
- linux期中架构文档,Linux期中架构 - osc_jbr77wuo的个人空间 - OSCHINA - 中文开源技术交流社区...
- powershell美化
热门文章
- 腾讯优图实验室招聘计算机视觉研究员和实习生
- 判断三条边能否构成三角形 python
- MQTT服务质量等级及抓包分析
- python模拟按键包_今天玩点啥:利用python之PyUserInput实现模拟鼠标键盘操作,抢红包?聊天?自动下载?...
- 会声会影2018 转码导出H.265/HEVC编码视频
- 通过天眼查查询相关企业信息
- C++ 数学与算法系列之高斯消元法求解线性方程组
- x264 2pass编码说明
- oracle、mysql创建用户赋DBA权限
- 线上3D产品展示的方式