剑指Offer
安洁莉娅丶
这个作者很懒,什么都没留下…
展开
-
剑指Offer:矩阵中的路径(JAVA实现)
原题:点击此处考点:DFS这是一道很容易就想到解法的题目。但是我首先想到的是BFS,BFS的解法不是不行,而是太过复杂,不适合面试的时候给出。DFS与BFS的时间复杂度是一样的,并且可以用递归实现,因此面试的时候应该用DFS更好一点。注意细节。各种返回的条件。class Solution { public boolean exist(char[][] board, String word) { char[] chs = word.toCharArray();原创 2021-03-01 21:41:25 · 131 阅读 · 0 评论 -
剑指Offer:剪绳子(JAVA实现)
原题:点击此处考点:动态规划本题也可以用数学来解,但是博主太过愚笨了,只能用动态规划来解了。0和1都是不可分割的,所以dp[0] = 0,dp[1] = 0假设当前数字为i那么 1<= j < idp[i] 在每一个j处都有两个抉择:要么直接取j * (i - j)要么i - j继续拆分,即j * dp[i-j]对每一个i都进行同样的操作时间复杂度:O(n2)空间复杂度:O(n)class Solution { public int cuttingRope(int原创 2021-03-01 20:42:59 · 148 阅读 · 0 评论 -
剑指Offer:最长不含重复字符的子字符串(JAVA实现)
原题:点击此处考点:动态规划、字符串本题很容易考虑到用动态规划,但是动态规划的条件是难点。需要考虑一个字符串中,之前的字符是否出现过。假设之前出现的字符位置是j现在出现的字符位置是i那么,考虑两种不同的情况1. dp[i-1] >= i - j2. dp[i-1] < i - j两种对应的加减不同。时间复杂度:O(n)空间复杂度:O(1)class Solution { public int lengthOfLongestSubstring(String s) {原创 2021-03-01 20:06:13 · 105 阅读 · 0 评论 -
剑指Offer:构建乘积数组(JAVA实现)
原题:点击此处考点:DP这里用了两个数组分别维护前缀和和后缀和。时间复杂度:O(n)空间复杂度:O(n)可以对空间进行压缩,但是实在不好理解,因此还是选择了这种做法:class Solution { public int[] constructArr(int[] a) { if(a.length == 0){ return new int[0]; } if(a.length == 1){ re原创 2021-02-28 19:30:49 · 79 阅读 · 0 评论 -
剑指Offer:把字符串转换成整数(JAVA实现)
原题:点击此处考点:如何用Int来判断数字越界方法:int boundary = Integer.MAX_VALUE / 10;如果 res > boundry 或 res == boundary && chs[i] > ‘7’ (这个是因为边界的最后一个数字为8)时间复杂度:O(n)空间复杂度:O(n)(使用trim,新创建一个String)自己写的较为复杂的代码:class Solution { public int strToInt(String s原创 2021-02-28 18:57:15 · 78 阅读 · 0 评论 -
剑指Offer:不用加减乘除做加法(JAVA实现)
原题:点击此处考点:位运算难点:这道题每一行代码都不能变更。每一个字母都不能错。步骤:首先用与运算算出进位的位置,为数字c然后用异或运算算出不需要进位的数字,并且用这个数字取代原本的a,不然无法进行后续运算把b变为新算出来的进位的数字cb不为0,进行循环class Solution { public int add(int a, int b) { while(b != 0){ int c = (a&b)<<1;原创 2021-02-28 14:01:05 · 77 阅读 · 0 评论 -
剑指Offer:求1+2+…+n(JAVA实现)
原题:点击此处考点:不用if的递归出口本题有很多限制,主要考点我认为是使用一个不用if的方法跳出递归。可以用短路&来进行这样的操作。时间复杂度O(n)空间复杂度O(n)class Solution { int res = 0; public int sumNums(int n) { boolean x = (n>1) && (sumNums(n-1)>0); res += n; return re原创 2021-02-28 13:39:07 · 124 阅读 · 0 评论 -
剑指Offer:翻转单词顺序(JAVA实现)
原题:点击此处考点:字符串处理、双指针这道题第一时间想到的应该是String的内置方法split()和trim()分别可以进行切分和去除收尾空格。但是面试不该使用上述的内置方法,因此使用双指针法,但是双指针也不是简单的。很容易踩到一些坑:最后拼接出来的字符串,尾部还是有“ ”,因此还是需要trim。substring() 不是 subString() 非常特别时间复杂度O(n)空间复杂度O(n)class Solution { public String reverseWor原创 2021-02-26 19:06:26 · 136 阅读 · 0 评论 -
剑指Offer:扑克牌中的顺子(JAVA实现)
原题:点击此处考点:排序,数学这道题想到可以用Max-min < 5来解决,但是没想到还有另外一个条件是除了joker,不能有重复的数字class Solution { public boolean isStraight(int[] nums) { Arrays.sort(nums); int joker = 0; for(int num:nums){ if(num == 0){ j原创 2021-02-26 18:16:48 · 261 阅读 · 0 评论 -
剑指Offer:和为s的连续正数序列(JAVA实现)
原题:点击此处考点:双指针,滑动窗口这道题是 和为s的两个数字 的加强版。本质还是双指针,但是这道题就比上面那道题没那么明显。通过这道题可以更深刻的体会到滑动窗口的有多实用。class Solution { public int[][] findContinuousSequence(int target) { List<int[]> list = new ArrayList<>(); for(int i = 1,j = 2;i<原创 2021-02-26 12:56:13 · 89 阅读 · 0 评论 -
剑指Offer:和为s的两个数字(JAVA实现)
原题:点击此处本题可以用双指针来进行解决。(原因:数组是排序数组,可以用双指针进行压缩)时间复杂度O(n)空间复杂度O(1)class Solution { public int[] twoSum(int[] nums, int target) { if(nums.length <= 1){ return new int[0]; } int a = 0; int b = 0; int原创 2021-02-26 11:47:09 · 114 阅读 · 0 评论 -
剑指Offer:数组中数字出现的次数 II(JAVA实现)
原题:点击此处考点:位运算本题与上一题相比,明显有混淆之意。这一题中数字出现了3次,因此异或就没有可用之处了,因为异或3次本身还是自己。本题的关键是:在二进制位中,如果出现了3次的位置,必定是3的倍数,因此对该位置进行余3操作,剩余的值便是唯一一个出现1次的数字在该位置的数字class Solution { public int singleNumber(int[] nums) { int[] bitNums = new int[32]; Arrays.f原创 2021-02-26 11:33:49 · 138 阅读 · 0 评论 -
剑指Offer:数组中数字出现的次数(JAVA实现)
原题:点击此处考点:异或本题关键词:数组中的数字只出现1次。遇到这种问题,第一时间想到的是异或,但是本题难度加大,是有两个数字出现一次。做法:相同的数字分为一组不同的两个数组分为不同组思路就是通过异或所有数字得到一个数,取这个数的其中一个不为0的位置。并把这个位置与所有数字进行AND操作,如果得到的为1,则为一组,如果为0,则为另一组。两个组分别进行异或,得到的就是答案的两个数字。class Solution { public int[] singleNumbers(int[原创 2021-02-25 13:15:03 · 130 阅读 · 0 评论 -
剑指Offer:平衡二叉树(JAVA实现)
原题:点击此处考点:二叉树、递归,DFS这题建立在深度的基础上,需要考虑的是递归的变化条件。时间复杂度O(n)空间复杂度O(n)class Solution { public boolean isBalanced(TreeNode root) { return culDepth(root) == -1?false:true; } public int culDepth(TreeNode root){ if(root == null){原创 2021-02-25 12:45:06 · 83 阅读 · 0 评论 -
剑指Offer:二叉树的深度(JAVA实现)
原题:点击此处考点:DFS、二叉树这道题很简单,不多描述class Solution { public int maxDepth(TreeNode root) { return maxDepth(root,0,0); } public int maxDepth(TreeNode root,int depth,int max){ if(root == null){ return depth; }原创 2021-02-25 11:11:45 · 98 阅读 · 0 评论 -
剑指Offer:两个链表的第一个公共节点(JAVA实现)
原题:点击此处我服了,这道题做了好几遍了,还是没想回来思路。考点:链表,双指针思路:两个指针都跑两条链表,遇到一起就是有公共节点,一起都为null就是无交点。public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode h1 = headA; ListNode h2 = headB; while(h原创 2021-02-24 18:07:56 · 86 阅读 · 0 评论 -
剑指Offer:数组中的逆序对(JAVA实现)
原题:点击此处考点:归并排序,分治思路:本题较难,不过本题主要的思想是分治的思想。本题计算逆序对只用了一行语句:count += (mid - i + 1);其余几乎都是归并排序的的代码,因此本题也可以作为归并排序的应用题。时间复杂度:O(nlogn)空间复杂度:O(n)分治为什么要用递归?因为分治需要的是从小问题的从头往上堆叠成一个大问题的解决方案。递归正好可以做到。class Solution { public int reversePairs(int[] nums)原创 2021-02-24 11:24:19 · 108 阅读 · 0 评论 -
剑指Offer:第一个只出现一次的字符(JAVA实现)
原题:点击此处题解:很容易想到用哈希表来进行处理。这里可以用有序的哈希表(LinkedHashMap),来进行判断。时间复杂度O(n)空间复杂度O(1)(因为必定只有26个字母)class Solution { public char firstUniqChar(String s) { Map<Character,Boolean> linkMap = new LinkedHashMap<>(); char[] chs = s.toC原创 2021-02-24 09:47:52 · 84 阅读 · 0 评论 -
剑指Offer:丑数(JAVA实现)
原题:点击此处初见,不会。看别人题解,得知此题可以用动态规划做出。因为质因数为2,3,5的数,必定可以通过之前的数算出的质因数来*2,*3,*5来计算出当前的数需要考虑的点:1. 如何避免重复(如果dp【a】*2,dp【b】*3 相等,a和b都要进行相加)2. 如何进行打表时间复杂度class Solution { public int nthUglyNumber(int n) { if(n <= 0){ return 0;原创 2021-02-24 09:24:27 · 89 阅读 · 0 评论 -
剑指Offer:最小的k个数(JAVA实现)
原题:点击此处考点:TopK:即前最大k个数或前最小k个数最大堆,最小堆快排这道题非常考验综合能力思路一:使用内置排序工具,进行排序,这个做法不明智。时间复杂度O(nlogn)空间复杂度O(1)思路二:(比较好实现)使用最大堆,来维持一个k大小的的堆。(手动实现一个堆也是不现实的,也要用内置工具函数,即PriorityQueue)时间复杂度O(nlogk)空间复杂度O(k)优点:不用改变数组思路三:(比较高效)利用快排的思想,将数组patition为k前和k后时间复杂度是O原创 2021-02-14 17:10:24 · 91 阅读 · 0 评论 -
剑指Offer:数组中出现次数超过一半的数字(JAVA实现)
原题:点击此处考点:哈希、排序、摩尔根投票法思路:哈希和排序都是很容易想出来的方法。摩尔根投票法:找出数组中超过一半的数字,如果数组中没有超过一半的数字,找出来的数字不是众数方法:选一个数作为众数。如果数组中当前遍历的数与他相同,则投票数+1如果不同,投票数-1如果投票数=0,重新选择众数,并开始重新计算最后得到的数字就是超过一半的数时间复杂度O(n)空间复杂度O(1)class Solution { public int majorityElement(int[]原创 2021-02-14 13:35:52 · 146 阅读 · 0 评论 -
剑指Offer:字符串的排列(JAVA实现)
原题:点击此处考点:字符串、回溯思路:本道题很容易就想到是回溯,难点是怎么实现回溯。对于字符串这个字符性质,用列表来进行不断地remove好像不太合适,因此本题采用的方法是:在当前位置的字符,不断地与后面的字符进行交换,当做完操作后,再换回来。而且要实现一个HashSet,这个原因是因为有可能会有这样的[a,a,c,v,b]这样的列表,其中a是有重复的,如果不用HashSet的话,就会出现重复。时间复杂度O(n!)(因为排列方案就是n × (n-1)× (n-2)……)空间复杂度O(n2原创 2021-02-14 13:20:12 · 117 阅读 · 0 评论 -
剑指Offer:二叉树中和为某一值的路径(JAVA实现)
原题:点击此处考点:二叉搜索树、先序遍历、回溯法思路:使用先序遍历来对二叉搜索树进行一个遍历,到达叶子节点就进行一个判断是否是目标结果,是则加入,不是则返回。当该节点进行过操作之后,就要把自己的操作给消去(回溯)时间复杂度O(n)空间复杂度O(n)/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode r原创 2021-02-14 12:13:34 · 104 阅读 · 0 评论 -
剑指Offer:二叉搜索树与双向链表(JAVA实现)
原题:点击此处考点:DFS、二叉搜索树、中序遍历、循环链表、双向链表思路:二叉搜索树的中序遍历必定是从小到大排序的,因此必定可以使用递归进行处理。运用了两个指针,分别是pre和cur来对链表的前后进行处理,还有head。当进行一轮之后dfs之后,head指向链表头,pre指向链表尾部,cur = null。因此可以做到循环链表的结构。/*// Definition for a Node.class Node { public int val; public Node le原创 2021-02-14 11:42:14 · 104 阅读 · 1 评论 -
剑指Offer:复杂链表的复制(JAVA实现)
原题:原题考点:链表,哈希思路一:比较容易想到的思路,用哈希表来记录已经遍历过的节点。时间复杂度O(n),空间复杂度O(n)思路二:三步骤:在原链表的基础上的每个节点的next进行复制对每个复制的节点进行random赋值对链表进行拆分三步骤的时间复杂度都是O(n),经过加法后还是O(n),空间复杂度为O(1)但是这个方法比较抽象,不过大思想是把东西都进行分开进行处理,合起来就是个完整的答案。思路一代码:/*// Definition for a Node.class N原创 2021-02-13 22:25:00 · 99 阅读 · 0 评论 -
剑指Offer:二叉搜索树的后序遍历序列(JAVA实现)
原题考点:栈、数、递归二叉搜索树、后序遍历思路:每次将二叉树分割成两部分,左子树与右子树如果节点数量<=1,则返回True如果节点数量不小于1,就要判断该子树是否符合后序遍历、的特点主要有两个判断点:p == j,用于判断是否是后序遍历recur(),用于判断子树class Solution { public boolean verifyPostorder(int[] postorder) { return recur(postorder,0,post原创 2021-02-13 21:24:40 · 168 阅读 · 1 评论 -
剑指Offer:从上往下打印二叉树(JAVA实现)
2021.2.13原题考点:树、队列思路:巧妙运用队列这个优秀的数据结构注意NULL的情况public class Solution { public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) { ArrayList<Integer> ans = new ArrayList<>(); if(root == null){ re原创 2021-02-13 19:20:59 · 123 阅读 · 0 评论 -
剑指 Offer:栈的压入、弹出序列
这道题是教科书里面常见的题。我的思路是用一个Set集合来记录出现过的元素,还有两个指针分别指向两个数组,写出来比较复杂,不过能解决问题。1、判断当前出栈元素是否已经在栈中。在:往下走。不在:就在入栈数组中找到这个元素位置为止一路入栈。这里有两个跳出的条件:①、一个是入栈数组已经全部入栈了。②、另一个是入栈数组当前位置和出栈要求的元素相同了。2、判断当前元素是不是栈顶元素。是:则把出栈数组的索引+1。不是:说明这个序列已经不是正确的了,return。时间复杂度O(n)空间复杂度O(原创 2020-12-09 13:31:16 · 143 阅读 · 0 评论 -
剑指Offer:顺时针打印矩阵(JAVA实现)
这题思路不难。很容易就想到了从左到右,从上到下从右到左从下到上难点在于各种边界条件的判定,还有大堆的if,else判断条件,如果是现场编写代码很难做到面面俱到。看了下别人的题解:觉得用边界压缩这个思路来编写代码是最简洁的。时间复杂度O(MN)空间复杂度O(1)用L,R,T,B分别记录左边界,右边界,上边界,下边界的位置。每一次循环都要进行边界的压缩,并且判断边界是否已经越界了。这种思路比用访问数组的思路要清晰,并且编写起来很舒适。class Solution { pub原创 2020-12-09 10:55:13 · 132 阅读 · 0 评论 -
剑指Offer:树的子结构(JAVA实现)
原题初见这题。只能想到有遍历去做,但是又无从下手。看完题解发现是两个递归。其中两个递归都是先序遍历,学习了。注意,力扣上这道题中的B树为Null也是false。但是在剑指Offer书上说的是B数为null时,返回的应该是true。这里我不是很懂,我觉得剑指Offer说的应该才是正确的。代码中涉及两个递归:1、isSubStructure(A,B),先序遍历A树,把当前节点作都和B树去做比较。2、recur(A,B),对比A,B两棵树是否是一致的。用语言还是很难表达清楚,用图形最好表达了,原创 2020-12-08 16:38:30 · 164 阅读 · 0 评论 -
剑指Offer:链表中倒数第k个结点
这题,有三个非法输入需要判断。1、K不能小于等于0.2、head不能为null.3、fast 不能跑出链表之外所以思路正确不代表代码正确。。一定要检查特殊条件public class Solution { public ListNode FindKthToTail(ListNode head,int k) { //判断非法输入 if(k <= 0){ return null; } if(head原创 2020-12-08 15:21:36 · 101 阅读 · 0 评论 -
剑指Offer:数值的整数次方(Java实现)
本题在面试中如果出现,属于考验代码鲁棒性的题目。考点:1、指数是负数的情况。2、如果是负数,需要1/基数,基数是0怎么办?3、快速幂的写法。粗暴的写法时间复杂度O(n)空间复杂度O(1)public class Solution { public double Power(double base, int exponent) { //1、第一种朴素一点的方法。 if(base == 0){ return 0; }原创 2020-12-08 11:43:07 · 139 阅读 · 0 评论 -
剑指Offer:二进制中1的个数(Java实现)
以前在力扣上做过只有正数的1的个数,是可以用动态规划来做的。这里的题按照书本所说,需要考虑到负数的情况。负数就非常麻烦。比如-10。正数是:0000…1010但是负数是:11111…0101(30个1,2个0)在书上有两种方法:一种是技巧法,可以记住,但是不适合现场想出来。即:n 与 n-1 相与会把最右边的一个1给去掉。public class Solution { public int NumberOf1(int n) { //技巧法 int原创 2020-12-07 23:26:25 · 117 阅读 · 0 评论 -
剑指Offer:重建二叉树(Java实现)
原题:点击此处这道题真的折磨了好几次,都还是不会。这次总结了几个关键点,希望下次再打的时候可以记住。关键点:可以使用哈希表来记住中序遍历的值对应的索引,这样就不用每次都过一次循环了。前序遍历最重要的作用就是找到根节点罢了,所以递归的时候传入根节点的位置就可以了,不用考虑前序遍历的开始和结束中序遍历要记住开始和结束,但是无论哪种情况,递归结束的重点都是left > right不要把tree当做参数传到递归里面,会引发引用错乱,而应该想下面的代码直接在递归中写出树的左节点和树的右节点。原创 2020-12-07 11:45:37 · 117 阅读 · 1 评论 -
剑指Offer:从尾到头打印链表(Java实现)
题目描述输入一个链表,按链表从尾到头的顺序返回一个ArrayList。法1:时间复杂度O(n)空间复杂度O(n)方法:创建栈/*** public class ListNode {* int val;* ListNode next = null;** ListNode(int val) {* this.val = val;* }* }**/import java.util.*;pub原创 2020-12-07 10:04:12 · 118 阅读 · 0 评论