剑指offer
刷题最重要的还是自己的逻辑思维能力,勤总结,勤思考,坚持下来肯定会有所提升的。
咖啡不加冰和糖
有志者,事竟成
展开
-
剑指Offer之数据流中的中位数
题目描述:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。思路分析:如果数字个数为偶数,中位数为中间的2个数的平均数,如:1,2,3,4,中位数为(2+3)/ 2 = 2.5如果数字个数为奇数,中位数为中间的数。如:1, 2, 3,中位数为 2;前提是数字先排好序。我们可以把数字分为2部分:前半部分和后半部分,前半部分用大顶堆B存储,则最大值在堆顶,原创 2020-08-14 13:52:10 · 148 阅读 · 1 评论 -
剑指Offer之剪绳子
题目描述:给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。参考代码:public int cutRope(int target) { if(target < 2)return 0; int[]原创 2020-08-13 22:05:15 · 65 阅读 · 0 评论 -
剑指Offer之矩阵中的路径
题目描述:参考代码: public boolean hasPath(char[] matrix, int rows, int cols, char[] word) { if(matrix == null || cols < 0 || rows < 0)return false; //转换为二维数组 int k = 0; char[][] board = new char[rows][cols]; for(int原创 2020-08-13 00:42:30 · 75 阅读 · 0 评论 -
剑指Offer之二插搜索树的第k大/小结点
说明:该题牛客和力扣有点区别,下面分别来进行解决。题目描述(1)力扣:给定一棵二叉搜索树,请找出其中第k大的节点。注意:这里是求第k大结点,而且题目给的返回值为int,是个数值。思路分析:求二插搜索树的第k大结点,则用右根左的方式遍历二叉树序列,结果为递减序列,找到其中的第k个元素即可。参考代码:class Solution { private int res;//定义成员变量 private int k;//定义成员变量 public int kthLarg原创 2020-08-11 10:51:41 · 109 阅读 · 0 评论 -
剑指Offer之删除排序链表中的重复结点
说明:该题有2种版本,力扣和牛客是不同的版本,先看力扣上面的简单的版本。题目描述:力扣:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。输入: 1->1->2输出: 1->2可以看到重复的元素只保留1个。参考代码:public ListNode deleteDuplicates(ListNode head) { if(head == null)return head; ListNode p = head; while(p != null &am原创 2020-08-11 09:34:53 · 221 阅读 · 0 评论 -
剑指Offer之二叉树的下一个结点
题目描述给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路分析参考分析主要分3中情况:(1)当前节点有右子树:返回当前节点右子树最左结点;(2)当前节点无右子树、是父节点的左子树中的结点:返回父节点;(3)当前节点无右子树、是父节点的右子树中的结点:找到一个节点,该结点的父节点的左直接左孩子是该结点,返回父节点。参考代码public TreeLinkNode GetNext(TreeLinkNo原创 2020-08-10 14:57:06 · 86 阅读 · 0 评论 -
剑指Offer之和为s的2个数字
题目描述:这道题牛客和力扣有小小的区别,力扣比较简单,直接输出符合条件的一个就行,而牛客要输出乘积最小的一个,稍微有点麻烦,但是思路大体相同。牛客题目描述:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。注意:对应每个测试案例,输出两个数,小的先输出。参考代码: public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {原创 2020-08-10 09:38:50 · 146 阅读 · 0 评论 -
剑指Offer之判断平衡二叉树
题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树参考代码:public boolean IsBalanced_Solution(TreeNode root) { if(root == null)return true; return judge(root) != -1;}public int judge(TreeNode root){ if(root == null)return 0; int原创 2020-08-10 08:47:20 · 94 阅读 · 0 评论 -
剑指Offer之二叉树的深度
题目描述:输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。参考代码:递归 public int maxDepth(TreeNode root) { if(root == null)return 0; return Math.max(maxDepth(root.left), maxDepth(root.right) + 1); }层序遍历public int TreeDepth(TreeNo原创 2020-08-09 23:26:22 · 92 阅读 · 0 评论 -
剑指Offer之判断一棵二叉树是不是对称
题目描述请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。参考代码boolean isSymmetrical(TreeNode root){ if(root == null)return true; LinkedList<TreeNode> queue = new LinkedList<>(); queue.addLast(root); queue.原创 2020-08-06 02:06:20 · 110 阅读 · 0 评论 -
2020-08-06
题目描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。思路分析:遍历数组,如果第index个位置的数字为index,i++;如果numbers[numbers[i]] == numbers[i],说明2个未知的元素重复,返回;否则,交换两个数字。参考代码:public b原创 2020-08-06 01:39:40 · 166 阅读 · 0 评论 -
剑指 Offer之最小的k个数
题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。思路分析:可以用容量为k的大顶堆来解决该题目,大顶堆堆顶元素最大,其他元素都小于堆顶元素,每当遇到比堆顶元素小的元素,就加入堆中,堆中元素个数为k+1时,删除堆顶元素。最后返回堆中的所有元素。参考代码: public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {原创 2020-08-05 21:45:55 · 134 阅读 · 0 评论 -
剑指Offer之连续子数组的最大和
题目描述:输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。参考代码:public int FindGreatestSumOfSubArray(int[] array) { if(array == null || array.length == 0)return 0; int sum = array[0]; int max = array[0]; for(int i = 1; i < arra原创 2020-08-05 21:19:23 · 150 阅读 · 0 评论 -
剑指Offer之跳台阶和变态跳台阶
题目一:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。参考代码:public int JumpFloor(int target) { if(target == 0)return 1; if(target == 1)return 1; int p1 = 1; int p2 = 1; for(int i = 2; i <= target; i++)原创 2020-08-04 08:57:32 · 154 阅读 · 0 评论 -
剑指Offer之复杂链表的复制
题目描述:请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。方法一:HashMap复制分2步走:把所有的结点放入map中;处理random指针方向。参考代码:public Node copyRandomList(Node head) { if(head == null)return head; Map<Node, Node原创 2020-07-14 10:40:53 · 90 阅读 · 0 评论 -
剑指Offer之最长不含重复字符的子字符串
题目描述:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。参考代码:public int lengthOfLongestSubstring(String s) { if(s == null || s.length() == 0)return 0; int res = 0; int left = 0; int right = 0; Map<Character, Integer> map = new HashMap<原创 2020-07-07 09:51:29 · 100 阅读 · 0 评论 -
剑指Offer之把数组排成最小的数
题目描述:输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。参考代码:public String minNumber(int[] nums) { if(nums == null || nums.length == 0)return ""; String[] str= new String[nums.lengtn]; for(int i = 0; i < nums.length; i++){ str[i] = String.va原创 2020-07-03 20:16:20 · 145 阅读 · 0 评论 -
剑指Offer之栈的压入、弹出序列
题目描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。参考代码:public boolean validateStackSequences(int[] pushed, int[] popped) { LinkedList<Integer>原创 2020-07-02 02:34:48 · 85 阅读 · 0 评论 -
剑指Offer之序列化二叉树
题目描述:题目: 请实现两个函数,分别用来序列化和反序列化二叉树。序列化: 将所给二叉树转化为字符串;反序列化:将字符串转化为二叉树思路分析:序列化时,可以采用BFS来遍历,运用辅助队列来进行层次遍历。反序列化要先构造结点,然后也是BFS进行操作。参考代码: //序列化二叉树 public String serialize(TreeNode root) { if(root == null)return "[]"; StringBuilder res = new Str原创 2020-06-29 18:53:46 · 140 阅读 · 0 评论 -
剑指Offer二叉树中和为某一值的路径
题目描述:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。思路分析:采用先序遍历思想,当遇到第1个结点curr,用sum-curr.val,然后将curr.val放入列表path中,当当前结点为叶子结点况且sum=0,将path加入结果集合中。否则将删除path的最后一个结点。结束本轮递归,进行下次递归。详细解析参考代码:private List<List<Integer>> res=原创 2020-06-29 15:34:17 · 102 阅读 · 0 评论 -
剑指之字符串的排列
题目描述:输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。示例:输入:s = “abc”输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]题目分析:题目分析参考代码: private char[] c; private List<String> res; public String[] permutation(String s) { if(s == null原创 2020-06-27 13:20:43 · 209 阅读 · 0 评论 -
剑指Offer之二叉搜索树与双向链表
题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。原创 2020-06-27 09:39:15 · 98 阅读 · 0 评论 -
剑指Offer之股票的最大利润
题目描述:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?题目分析:第1天的最大利润为:0;第2天的最大利润为:max(前2天前的最大利润,第2天的价值 - 第2天前的最小价值);第3天的最大利润为:max(第3天前的最大利润,第3天的价值 - 第3天前的最小价值);第4天的最大利润为:max(第4天前的最大利润,第4天的价值 - 第4天前的最小价值);…第i天的最大利润为:max(第i天前的最大利润,第i天的价值 - 第i天前的最小价值)原创 2020-06-26 20:53:58 · 173 阅读 · 0 评论 -
剑指Offer之礼物的最大价值
题目描述:在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?题目分析:此类题目做的多了,思路就比较清晰了。下面用例子来说明:设棋盘如下:(grid[]来表示棋盘:3 x 3)【1, 3, 1】【1, 5, 1】【4, 2, 1】现在来分析:设置一个数组res[][],记录走过路线上的最大值。如果原创 2020-06-26 20:01:32 · 113 阅读 · 0 评论 -
剑指Offer之队列的最大值
题目描述:请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。若队列为空,pop_front 和 max_value 需要返回 -1。思路分析:该题和实现最小栈类似。我们可以设置一个辅助队列:1)当元素进队列时,元素进队列的同时,判断:如果当前进队元素value > 辅助队列中的某些元素,辅助队列尾部小于value的元素循环出队,最后较大的value进入辅助队列。这一步完成原创 2020-06-23 21:57:16 · 161 阅读 · 0 评论 -
剑指Offer之从上到下打印二叉树 III
题目描述:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。参考代码: public List<List<Integer>> levelOrder(TreeNode root) { LinkedList<List<Integer>> res = new LinkedList<>();//存放结果的列表 LinkedList<原创 2020-06-23 20:13:28 · 78 阅读 · 0 评论 -
剑指Offer之数组中数字出现的次数
题目描述:一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。示例 1:输入:nums = [4,1,4,6]输出:[1,6] 或 [6,1]题目分析:我们可以将所有的元素进行 ^ 操作,结果为出现了1次的2个元素相 ^ 的结果res,那么怎么分别得到这2个数字呢?我们可以设置临时变量t = 1;让 t 和 res进行 & ,如果t & res == 0,t<<1;否原创 2020-06-23 11:48:45 · 93 阅读 · 0 评论 -
剑指Offer之把字符串转换成整数
题目描述:写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。说明:假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。思路分析:去掉字符串左边的空格,然后从头往后遍历,如果第一位为+或者-,往后遍历,如果遇到非数字,结束循环,如果是数字,将数字记录下来。注意:本题难点在于如何处理溢出问题原创 2020-06-23 08:26:49 · 99 阅读 · 0 评论 -
剑指Offer之1~n的整数中1出现的次数
题目描述:输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。思路分析:常规思路是输入一个整数n,循环判断每个数字中1的个数,然后累加起来,但是这样在n比较大的时候,会超时,这里分享一个不错的思路:思路。参考代码:public int countDigitOne(int n) { if(n < 1)return 0; int round = n; int base =原创 2020-06-22 13:21:08 · 153 阅读 · 0 评论 -
剑指Offer之第n个丑数
题目描述:题目:我们把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。示例:输入: n = 10输出: 12解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。注意: 1也是丑数。思路分析:分享一个个人觉得不错的题解:题解参考代码:public int nthUglyNumber(int n) { if(n < 0)return -1; int a = 0; int b原创 2020-06-22 10:46:12 · 139 阅读 · 0 评论 -
剑指Offer之构建乘积数组
题目描述:给定一个数组 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]。不能使用除法。题目分析:刚开始看题目,题目都没看懂,后来才知道题目意思:给你一个数组a[],你需要做的就是输出数组b[],它的第 i 项的元素等于a数组的每项元素的乘积,注意:1)这个乘积不包括第 i 项。2)题目明确说明,不能用除法。思路分析:bb[0]1a[1]原创 2020-06-22 09:46:56 · 105 阅读 · 0 评论 -
剑指Offer之约瑟夫环问题求解
题目描述:题目: 0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。思路分析:思路分析:这里分享自己觉得比较好的分析----思路分析参考代码:public int lastRemaining(int n, int m) { int res = 0; for(int i =原创 2020-06-21 14:31:09 · 107 阅读 · 0 评论 -
剑指Offer之滑动窗口的最大值
题目描述:给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。示例:输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 ; 输出: [3,3,5,5,6,7]题目分析:从头到尾遍历元素,元素的索引进队列:当队列为null时,元素索引进队列;若nums[i] >= queue.peekLast();元素循环出队;若nums[i] < queue.peekLast();元素进队;判断:若 i - k == queue.peek原创 2020-06-20 21:04:55 · 72 阅读 · 0 评论 -
剑指Offer之左旋字符串
题目描述:题目:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。注意:输入的n表示第n个,显然是从1开始计数的。参考代码:代码1public String reverseLeftWords(String s, int n) { if(s == null || s.length() == 0)return s; if(n原创 2020-06-18 14:05:09 · 72 阅读 · 0 评论 -
剑指Offer之左旋单词顺序
题目描述:题目:输入一个英文句子,翻转句子中单词的顺序,但单词内 字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。注意:输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。思路分析:去掉单词前后的空字符串;设置两个指针left和right,left一直向前移动,直到遇到空格” “停下来,将区间lef原创 2020-06-18 13:49:48 · 122 阅读 · 0 评论 -
剑指Offer之和为s的连续正数序列
题目描述:输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。思路分析:思路分析参考代码:public int[][] findContinuousSequence(int target) { int i = 1; int j = 1; int sum = 0; List<int[]> res = new ArrayList<>();原创 2020-06-16 23:55:10 · 89 阅读 · 0 评论 -
剑指Offer之0~n-1中缺失的数字
题目描述:一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。思路分析:可以考虑用二分法来解决问题:令mid = (left + right) / 2;当中间元素等于mid = nums[mid]时,说明缺失的数字在后面,令 left = mid + 1;当中间元素等于mid != nums[mid]时,说明缺失的数字在前面;令 right= mid - 1;最后返回left。原创 2020-06-15 12:59:46 · 147 阅读 · 0 评论 -
剑指Offer之最小栈
题目描述:题目: 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。要求:push(x) —— 将元素 x 推入栈中。pop() —— 删除栈顶的元素。top() —— 获取栈顶元素。getMin() —— 检索栈中的最小元素。思路分析:题目的关键是可以得到栈中的最小值,我们可以用一个辅助栈minStack来解决问题:当元素进栈时,若辅助栈为null或者进栈元素小于等于辅助栈的栈顶元素,元素进栈的同时,也进辅助栈;当元素出栈时,若出栈元素和辅助栈原创 2020-06-15 11:52:29 · 96 阅读 · 0 评论 -
剑指Offer之顺时针打印矩阵
题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]输出:[1,2,3,6,9,8,7,4,5]参考代码: public int[] spiralOrder(int[][] matrix) { if(matrix == null || matrix.length == 0)return new int[]{}; int left = 0; int right = mat原创 2020-06-15 07:58:45 · 86 阅读 · 0 评论 -
剑指Offer之不用加减乘除做加法
题目描述:难度简单34写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。思路分析:2个十进制数相加,和 = 【 对应位置数字相加的和 + 低位置在该位置的进位】;二进制相加也是一样,设2个二进制数a,b:sum = a + b(不计进位),carry = 进位;将上次的sum 和 进位carry<<1相加,结果赋值给sum ,carry = 新产生的进位;重复2,直到进位carry=0;第1步的加法做完之后,如果还有进位,那原创 2020-06-13 11:15:19 · 144 阅读 · 0 评论