剑指offer
剑指offer的刷题解答
chenziang1
这个作者很懒,什么都没留下…
展开
-
JZ12 矩阵中的路径
例如 \begin{bmatrix} a & b & c &e \\ s & f & c & s \\ a & d & e& e\\ \end{bmatrix}\quad⎣⎡asabfdcceese⎦⎤ 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。数据范围:0 \le n,m \le 20\0≤n,m≤20 ,1\le len \le 25\1≤len≤25。原创 2022-09-21 18:28:30 · 181 阅读 · 0 评论 -
JZ46 把数字翻译成字符串
1. 最好一开始有个预留的比如do【0】是没有意义的表示初值为1,这样比较好,因为递推有i-2所以必须两个初值,如果计算两个有意义的话,很难。在该字符和前一个字符为11-19和21-26的时候dp[i]=dp[i-1]+dp[i-2],其他时候为dp【i-2】2.考虑清楚0的作用有的时候由于0导致整个无意义,而且10和20只有一种可能这两点需要注意。有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。进阶:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)原创 2022-09-21 16:14:23 · 181 阅读 · 0 评论 -
JZ48 最长不含重复字符的子字符串
以i结尾的情况下,递推的话不好搞因为当发生重复的时候,其实不是变成单一字符了,而是在之前还有一部分是连续不重复字符,我们需要找到之前的重复字符的位置,然后在得到新的dp【i】。于是想到了双指针,一遍遍历,一遍保存一个不重复的hashset,接着直到重复了,我们就向前一直遍历直到找到重复元素,之前的都删除,dp就是两个指针的差值。尝试了两种方向,一个是dp[i]表示以第i个字符结尾的最长子字符串,一个是表示前i个最长子字符串。请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。原创 2022-09-20 19:39:03 · 209 阅读 · 0 评论 -
JZ47 礼物的最大价值
在一个m\times nm×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?那么路径 1→3→5→2→1 可以拿到最多价值的礼物,价值为12。如输入这样的一个二维数组,动态规划,找到递归式子。原创 2022-09-20 18:42:28 · 73 阅读 · 0 评论 -
JZ63 买卖股票的最好时机(一)
在第3天(股票价格 = 2)的时候买入,在第6天(股票价格 = 7)的时候卖出,最大利润 = 7-2 = 5 ,不能选择在第2天买入,第3天卖出,这样就亏损7了;假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益。1.你可以买入一次股票和卖出一次股票,并非每天都可以买入或卖出一次,总共只能买入和卖出一次,且买入必须在卖出的前面的某一天。要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)原创 2022-09-20 17:59:06 · 84 阅读 · 0 评论 -
JZ70 矩形覆盖
我们可以用 2*1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 2*1 的小矩形无重叠地覆盖一个 2*n 的大矩形,从同一个方向看总共有多少种不同的方法?进阶:空间复杂度 O(1)\O(1) ,时间复杂度 O(n)\O(n)数据范围:0 \le n \le 38 \0≤n≤38。注意:约定 n == 0 时,输出 0。原创 2022-09-20 16:11:01 · 69 阅读 · 0 评论 -
JZ19 正则表达式匹配
3. 最后一个难点,计算,因为计算必须有初始值才行,我们先初始化一些东西,但是这里又来一个问题,那就是i=0的时候很难初始化,这里我们又需要得出一个递推公式,先把这一行计算出来,然后在递推。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。2.pattern 只包含从 a-z 的小写字母以及字符 . 和 *,无连续的 '*'。中间的*可以出现任意次的a,所以可以出现1次a,能匹配上。2.模式中的字符'*'表示它前面的字符可以出现任意次(包含0次)。原创 2022-09-20 15:52:44 · 196 阅读 · 0 评论 -
JZ42 连续子数组的最大和
输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,子数组最小长度为1。求所有子数组的和的最大值。经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18。动态规划,每一个dp[i]表示的是以array【i】结尾的最大子数组的和。要求:时间复杂度为 O(n)O(n),空间复杂度为 O(n)O(n)进阶:时间复杂度为 O(n)O(n),空间复杂度为 O(1)O(1)最后我们减少空间复杂度,用temp简化。递推公式就是如代码所示。原创 2022-09-16 13:56:27 · 68 阅读 · 0 评论 -
JZ85 连续子数组的最大和(二)
经分析可知,最大子数组的和为4,有[4],[4,-1,1],[1,2,-3,4],[1,2,-3,4,-1,1],故返回其中长度最长的[1,2,-3,4,-1,1]1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组。经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18,故返回[3,10,-4,7,2]3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组。原创 2022-09-16 13:53:42 · 86 阅读 · 0 评论 -
JZ44 数字序列中某一位的数字
数字以 0123456789101112131415... 的格式作为一个字符序列,在这个序列中第 2 位()是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。数据范围: 0 \le n \le 10^9 \0≤n≤109。原创 2022-09-13 17:14:49 · 88 阅读 · 0 评论 -
JZ38 字符串的排列
互异性:假设两个不一样的path导致一样的str,是不可能的,因为每一个char在之后都不可能再对他进行改变,每次都是char《--》char+1,char+2,char+3.....size 接着就是char+1开头了,这样的话不可能再后面的时候又把char位置的字符变为和另一个一样的,所以他们不一样,而一共就只有n的阶乘个不一样的,所以结论正确。1.java的函数参数都是传值的,但是string类型也是放入堆栈的,其他的对象都是传值放入的引用。3. string的length()函数查看长度,原创 2022-09-13 16:23:19 · 161 阅读 · 0 评论 -
JZ11 旋转数组的最小数字
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。2. 为什么选择右边的边界!第一:两个数字的时候可行 第二:没有旋转的时候可行,第三:重复多个数字的时候ok。1.二分查找的while循环内部判断的时候的等于号是决定了只有两个数字的时候,该选择哪一个数字。要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn)原创 2022-09-13 14:58:16 · 96 阅读 · 0 评论 -
JZ4 二维数组中的查找
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。数据范围:矩阵的长宽满足 0 \le n,m \le 5000≤n,m≤500 , 矩阵中的值满足 0 \le val \le 10^90≤val≤109。这个成立是因为,右移之后,原本元素的上面所有元素就永远不可能被搜索到了,因为没有左移操作,而那些元素必定小于target。进阶:空间复杂度 O(1)O(1) ,时间复杂度 O(n+m)O(n+m)不存在3,返回false。原创 2022-09-11 11:43:54 · 132 阅读 · 0 评论 -
JZ53 数字在升序数组中出现的次数
1.把原始的问题分类为二分查找的问题-》找到重复数组的左右边界相减得到重复的数量。这里需要注意的有while循环里面l r的关系。2. 学习二分查找的模板,模板如博文所言。(建议使用题目的样例去试一试)原创 2022-09-11 10:32:12 · 104 阅读 · 0 评论 -
JZ59 滑动窗口的最大值
JZ59 滑动窗口的最大值原创 2022-09-10 17:36:35 · 126 阅读 · 0 评论 -
JZ73 翻转单词序列
JZ73 翻转单词序列原创 2022-09-10 16:12:18 · 71 阅读 · 0 评论 -
JZ30 包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。输入: ["PSH-1","PSH2","MIN","TOP","POP","PSH1","TOP","MIN"]"POP"表示弹出栈顶元素,弹出2,栈中元素为-1。"PSH-1"表示将-1压入栈中,栈中元素为-1。"PSH2"表示将2压入栈中,栈中元素为2,-1。"PSH1"表示将1压入栈中,栈中元素为1,-1。输出: -1,2,1,-1。原创 2022-08-21 18:08:05 · 54 阅读 · 0 评论 -
JZ9 用两个栈实现队列
JZ9 用两个栈实现队列原创 2022-08-21 17:31:06 · 63 阅读 · 0 评论 -
JZ86 在二叉树中找到两个节点的最近公共祖先
JZ86 在二叉树中找到两个节点的最近公共祖先原创 2022-08-21 11:52:40 · 116 阅读 · 0 评论 -
JZ68 二叉搜索树的最近公共祖先
JZ68 二叉搜索树的最近公共祖先原创 2022-08-21 10:01:16 · 73 阅读 · 0 评论 -
剑指offer 序列化二叉树
序列化二叉树原创 2022-07-26 16:58:04 · 104 阅读 · 0 评论 -
剑指offer 二叉树的下一个节点
题目描述给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示思路首先我们的思路一定是遍历然后直接搞出来,而且他的时间复杂度也满足要求,但是这里我们有parent指针,可以有更技巧的方法。对于选定节点他作为根节点的子树肯定是左中右顺序遍历的那么如果他的右节点存在,他的下一个就应该是右子树的第一个节点也就是右节原创 2022-02-26 21:52:43 · 116 阅读 · 0 评论 -
剑指offer 判断是不是平衡二叉树
题目思路首先复习一下平衡二叉树,一般来说平衡二叉树都是搜索树,因为这个是为了使得搜索树的层数尽可能少造的树,从而使得搜索的时间不是最坏情况其实判断是否是avt就是看左右两颗子树的层高之差,然后在递归的判断左右两颗子树,但是这个样子的话,时间复杂度满足不了,因为每一次调用函数都要求一次层高。所以我们考虑,能不能把求层高和判断结合起来。求层高其实也是一个递归的函数,左子树和右子树的层高中较高的一个加一。和判断avt差不多。所以我们考虑把定义一个全局变量flag,在求层高的时候 ,如果有不满足avt原创 2022-02-26 21:23:24 · 201 阅读 · 0 评论 -
剑指offer 二叉搜索树与双向链表
题目思路使用堆栈中序遍历二叉搜索树每次保存上一个节点,然后把上一个节点的right指向当前节点,把当前节点的left指向上一个节点遍历一遍之后,就得到了一个双向链表注意一些初始量的设置比如prev一开始是一个新节点最后要把这个指向新节点的指针指向null,因为链表的第一个节点指向null,接着由我们创造的新节点的left访问到第一个节点返回。使用递归来遍历所有的节点,其他和上面一样对于思路二进行一些微调,考虑到这个遍历除了第一次我们的prev不和node进行连接之外,其他的node都要和原创 2022-02-26 20:38:10 · 192 阅读 · 0 评论 -
剑指offer 二叉树之中为某一直的路径是否存在
题目思路思路一:使用DFS来做想到这个是应为每次得到一条路径的时候,如果他不是目标路径,我们回退的时候,是需要把路径上面节点的值减去的,这个让我想到了DFS在每次调用的时候函数里面都可以一开始加上这个值最后减去这个值思路二:递归的方法分解为找寻子树是是sum-root。val的值的路径结束条件是一个没有孩子的节点的值是sum的值或者该节点是一个空节点。代码import java.util.*;/* * public class TreeNode { * int val =原创 2022-02-21 21:32:27 · 179 阅读 · 0 评论 -
剑指offer 二叉搜索树的后序遍历
题目思路使用递归的方法一个树,左子树是二叉搜索,右子树是二叉搜索,那么只要左边的都比root小,右边的都比root大那么他就是一个二叉搜索树。结束条件是没有节点和一个节点的时候都是二叉搜索树代码import java.util.*;public class Solution { public boolean VerifySquenceOfBST(int [] sequence){ int num=sequence.length;原创 2022-02-21 19:59:44 · 101 阅读 · 0 评论 -
剑指offer 二叉树的镜像
题目思路递归的思想结束条件是空树的镜像就是左子树的镜像放在右子树右子树的镜像放在左子树思路二:实际上经过几个例子之后我们可以发现只需要让每个节点都交换左右就可以了,所以我们遍历所有节点交换左右代码import java.util.*;/* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * public TreeNode(int原创 2022-02-21 17:12:35 · 50 阅读 · 0 评论 -
剑指offer 树的子结构
题目思路首先我们想到递归的方法也就是看看本节点是不是给定结构的相似根节点,如果不是看看左子树和有子树里面包不包含这个该结构本题的难点在于,查看本节点是否是相似结构的根节点的时候,也需要一个递归才能实现因为目的结构可以是无限大的所以我们需要额外的实现一个similar函数来看两个结构是否是相似的。代码/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null;原创 2022-02-21 16:43:57 · 41 阅读 · 0 评论 -
剑指offer 重建二叉树
题目import java.util.*;/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */import java.util.*;public class Solution { public TreeNode r原创 2022-02-21 15:54:26 · 243 阅读 · 0 评论 -
剑指offer 按照之字形打印二叉树
bfs通常使用队列,而dfs使用栈原创 2022-02-20 20:44:37 · 100 阅读 · 0 评论 -
剑指offer 二叉树深度
/**public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) { this.val = val;}}*/public class Solution {public int TreeDepth(TreeNode root) {if(root==null)return 0;return TreeDepth(root.left)&原创 2022-02-20 18:52:51 · 44 阅读 · 0 评论 -
剑指offer 删除链表中的重复节点
题目解思路移动指针的方法就行,主要是要考虑到很多特殊情况下也成立注意不能使得p.val之中的p是null会报错/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; }}*/public class Solution { public ListNode deleteDuplication(ListNod原创 2022-02-20 17:38:46 · 95 阅读 · 0 评论 -
剑指offer 从尾到头遍历链表 详解
剑指offer 从尾到头遍历链表 详解原创 2022-02-14 12:17:58 · 474 阅读 · 0 评论 -
剑指offer 反转链表
剑指offer 反转链表题目描述解题思路首先使用循环来解决本次循环的node是cur每次循环的时候把自身的next指向之前一个node,然后把cur赋值为下一个node,再次进行这个过程这里面有三个问题第一个是之前的node怎么表示,我们用prev来存储,它有一个初始值,每次循环的时候进行对他的值进行更新为cur第二是我们已经把cur.next赋值为prev了,怎么把找到cur的下一个node,这里我们在cur.next还没有赋值的时候就把cur.next存在next里面,然后在cur.原创 2022-02-14 17:39:00 · 117 阅读 · 0 评论 -
剑指offer 两个链表的第一个公共节点
剑指offer原创 2022-02-20 14:24:55 · 257 阅读 · 0 评论 -
剑指offer 合并有序链表 递归方法
问题思路使用递归的方法的要求当数据较小的时候很好计算数据交大的时候可以分解成数据很小的时候的情况递归方法的三个要点3. 结束的条件 这里是当一个链表是空的时候4. 结束的时候的动作 这里是直接把非空的链表返回或者两个都是空的返回空5. 怎么把大问题分解为小问题 这里是取两个链表的头,然后拿小的作为总链表的头,指向其他所有链表合并之后的头结点。代码/*public class ListNode { int val; ListNode next = null;原创 2022-02-14 18:05:54 · 136 阅读 · 0 评论 -
剑指offer 合并两个递增链表
题目思路对于大多数情况而言先找到两个链表里面较小的值当做起点cur然后list1的下一个需要比较的节点作为next1,list2的下一个需要比较的节点作为next2比较next1和next2cur.next指向较小的那个链表节点更新cur和next 不断循环直到有一个next是null 就直接把cur.next指向不为空的那个next特殊情况对于list1,list2有一个为空的情况,返回拎一个list就行代码/*public class ListNode {原创 2022-02-14 17:45:44 · 83 阅读 · 0 评论