剑指offer
剑指offer已经被人写烂了,但是每个人解题的思路不同,还是决定写一下,提升自己的同时也希望给他人一些启发。
安牛牛牛
没有感情的刷子
展开
-
实现前缀树
Trie(发音类似 “try”)或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。请你实现 Trie 类:Trie() 初始化前缀树对象。void insert(String word) 向前缀树中插入字符串 word 。boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。boolean startsWith(S原创 2022-02-28 16:31:05 · 139 阅读 · 0 评论 -
出现频率最高的k个数字
给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。示例 1:输入: nums = [1,1,1,2,2,3], k = 2输出: [1,2]示例 2:输入: nums = [1], k = 1输出: [1]提示:1 <= nums.length <= 105k 的取值范围是 [1, 数组中不相同的元素的个数]题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的思路:类似于这种第k大、第k原创 2022-02-28 16:18:02 · 704 阅读 · 0 评论 -
矩阵中的最大矩形
给定一个由 0 和 1 组成的矩阵 matrix ,找出只包含 1 的最大矩形,并返回其面积。注意:此题 matrix 输入格式为一维 01 字符串数组。示例1:输入:matrix = [“10100”,“10111”,“11111”,“10010”]输出:6解释:最大矩形如上图所示。示例 2:输入:matrix = []输出:0示例 3:输入:matrix = [“0”]输出:0示例 4:输入:matrix = [“1”]输出:1示例 5:输入:matrix = [“00原创 2021-12-13 22:13:51 · 1168 阅读 · 0 评论 -
直方图最大矩形面积
给定非负整数数组 heights ,数组中的数字用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。示例 1:输入:heights = [2,1,5,6,2,3]输出:10解释:最大的矩形为图中红色区域,面积为 10示例 2:输入: heights = [2,4]输出: 4提示:1 <= heights.length <=1050 <= heights[i] <= 104思路:用一个单调递增的栈原创 2021-12-09 17:02:34 · 325 阅读 · 0 评论 -
剑指offerⅡ 038 每日温度
请根据每日 气温 列表 temperatures ,重新生成一个列表,要求其对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。示例 1:输入: temperatures = [73,74,75,71,69,72,76,73]输出: [1,1,4,2,1,1,0,0]示例 2:输入: temperatures = [30,40,50,60]输出: [1,1,1,0]示例 3:输入: temperatures = [30,60原创 2021-12-08 13:22:31 · 82 阅读 · 0 评论 -
字符串中的变位词
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的某个变位词。换句话说,第一个字符串的排列之一是第二个字符串的 子串 。示例 1:输入: s1 = "ab" s2 = "eidbaooo"输出: True解释: s2 包含 s1 的排列之一 ("ba").示例 2:输入: s1= "ab" s2 = "eidboaoo"输出: False提示:1 <= s1.length, s2.length <= 104s1 和 s2 仅包含小写字母原创 2021-11-18 14:40:18 · 380 阅读 · 0 评论 -
0和1个数相同的子数组
给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。示例 1:输入: nums = [0,1]输出: 2说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。示例 2:输入: nums = [0,1,0]输出: 2说明: [0, 1] (或 [1, 0]) 是具有相同数量 0 和 1 的最长连续子数组。提示:1 <= nums.length <= 105nums[i] 不是 0 就是 1思路:原创 2021-11-18 11:58:31 · 335 阅读 · 0 评论 -
和为k的子数组
给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。示例 1 :输入:nums = [1,1,1], k = 2输出: 2解释: 此题 [1,1] 与 [1,1] 为两种不同的情况示例 2 :输入:nums = [1,2,3], k = 3输出: 2提示:1 <= nums.length <= 2 * 104-1000 <= nums[i] <= 1000-107 <= k <= 107思路:前缀和的方法。mp原创 2021-11-17 16:17:27 · 80 阅读 · 0 评论 -
乘积小于K的子数组
给定一个正整数数组 nums和整数 k ,请找出该数组内乘积小于 k 的连续的子数组的个数。示例 1:输入: nums = [10,5,2,6], k = 100输出: 8解释: 8 个乘积小于 100 的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。需要注意的是 [10,5,2] 并不是乘积小于100的子数组。示例 2:输入: nums = [1,2,3], k = 0输出: 0提示:1 <= nu原创 2021-11-17 15:18:11 · 142 阅读 · 0 评论 -
和大于等于target的最短子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。示例 1:输入:target = 7, nums = [2,3,1,2,4,3]输出:2解释:子数组 [4,3] 是该条件下的长度最小的子数组。示例 2:输入:target = 4, nums = [1,4,4]输出:1示例 3:原创 2021-11-17 14:25:39 · 322 阅读 · 0 评论 -
单词长度的最大乘积
给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。示例 1:输入: words = ["abcw","baz","foo","bar","fxyz","abcdef"]输出: 16 解释: 这两个单词为 "abcw", "fxyz"。它们不包含相同字符,且长度的乘积最大。示例 2:输入: words = ["a","ab","ab原创 2021-11-16 14:39:58 · 107 阅读 · 0 评论 -
前n个数字二进制中1的个数
给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。示例 1:输入: n = 2输出: [0,1,1]解释: 0 --> 01 --> 12 --> 10示例 2:输入: n = 5输出: [0,1,1,2,1,2]解释:0 --> 01 --> 12 --> 103 --> 114 --> 1005 --> 101说明 :0 <= n <= 1原创 2021-11-15 14:30:21 · 839 阅读 · 0 评论 -
构建乘积数组
给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。示例:输入: [1,2,3,4,5]输出: [120,60,40,30,24]提示:所有元素乘积之和不会溢出 32 位整数a.length <= 100000思路:可以分为上三角和下三角,下三角乘积:B[i] * =A[i-1];上三角乘原创 2021-11-14 17:27:05 · 325 阅读 · 0 评论 -
不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。示例:输入: a = 1, b = 1输出: 2提示:a, b 均可能是负数或 0结果不会溢出 32 位整数思路:通过与运算和左移运算,算出进位、通过异或运算算出当前位加完后的结果。先算不进位的结果,然后再加上进位的结果。只要有进位就一直加,直到没有进位int add(int a, int b) { while(b != 0) { // 当进位为 0 时跳出 lo原创 2021-11-14 16:57:08 · 312 阅读 · 0 评论 -
求 1+2+...+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。示例 1:输入: n = 3输出: 6示例 2:输入: n = 9输出: 45限制:1 <= n <= 10000思路:第一种方法:递归,由于不能用条件判断语句,可以用与操作的特性来判断n是否为0,如果n为0,则不执行后面的表达式,直接返回。第二种方法:用加法和位运算模拟乘法。对于AB,如果B的二进制下表示第i位为1,则这一位对原创 2021-11-14 16:22:29 · 694 阅读 · 0 评论 -
n个骰子的点数
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。示例 1:输入: 1输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]示例 2:输入: 2输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.0原创 2021-11-10 11:30:57 · 213 阅读 · 0 评论 -
滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。示例:输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3输出: [3,3,5,5,6,7]解释:滑动窗口的位置最大值[1 3 -1] -3 5 3 6 731 [3 -1 -3] 5 3 6 731 3 [-1 -3 5] 3 6 751 3 -1 [-3 5 3] 6 751 3 -1 -3 [原创 2021-11-08 16:30:37 · 234 阅读 · 0 评论 -
数组中数字出现的次数 Ⅱ
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。示例 1:输入:nums = [3,4,3,3]输出:4示例 2:输入:nums = [9,1,7,9,7,9,7]输出:1限制:1 <= nums.length <= 100001 <= nums[i] < 231思路:统计所有数字二进制上每一位的1出现的次数和,对1出现的次数除三取余,结果就是只出现一次的数字的二进制的值。此方法可以求一个数字只出现一原创 2021-11-08 14:12:47 · 95 阅读 · 0 评论 -
在排序数组中查找数字 Ⅰ
统计一个数字在排序数组中出现的次数。示例 1:输入: nums = [5,7,7,8,8,10], target = 8输出: 2示例 2:输入: nums = [5,7,7,8,8,10], target = 6输出: 0提示:0 <= nums.length <= 105-109 <= nums[i] <= 109nums 是一个非递减数组-109 <= target <= 109思路:通过二分法分别找到左边第一个target出现的原创 2021-11-08 11:32:55 · 82 阅读 · 0 评论 -
数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。示例 :输入: [7,5,6,4]输出: 5限制:0 <= 数组长度 <= 50000思路:直接暴力求解会超时,可以用归并排序做,在归并排序合并时做一个判断,设合并时左边的数组从l开始,右边从mid+1开始,i=l,j=mid+1;当nums[i]<=nums[j]时,nums[i]大于所有的nums[j]左边的数,nums[i]可以和mid+1原创 2021-11-05 14:56:29 · 50 阅读 · 0 评论 -
把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。示例 :输入: 12258输出: 5解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"提示:0 <= num < 231思路:简单的动态规划。先把数字转换为字符串,方便遍历。对于每一原创 2021-11-02 16:07:00 · 145 阅读 · 0 评论 -
把数组排成最小的数
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。示例 :输入: [10,2]输出: "102"输入: [3,30,34,5,9]输出: "3033459"提示:0 < nums.length <= 100说明:输出结果可能非常大,所以你需要返回一个字符串而不是整数拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0思路:数字的大小,和转化成字符串后字典序的大小是一致的。所以本质上是一个排序题,对于两个字符串a原创 2021-11-02 15:58:11 · 237 阅读 · 0 评论 -
数字序列中某一位的数字
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。示例 1:输入:n = 3输出:3示例 2:输入:n = 11输出:0限制:0 <= n < 231思路:digit:表示当前数字是几位数。start:表示位数为digit的数是从哪一个数开始的。count表示位数为digit的数字共占了多少位。从1开始计算,1原创 2021-11-02 14:11:52 · 137 阅读 · 0 评论 -
1~n 中整数1出现的次数
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。示例 :输入:n = 12输出:5输入:n = 13输出:6限制:1 <= n < 2^31思路:统计1~n中1出现的次数,可以统计1 ~ n中各个位上1出现的次数然后相加,个位上1出现的次数+十位上1出现的次数+百位上1出现的次数+ … 。数字1出现的次数:n10k+1{n} \over {10^{k+1}原创 2021-10-29 16:44:55 · 882 阅读 · 0 评论 -
剑指 Offer 38. 字符串的排列
输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。示例:输入:s = "abc"输出:["abc","acb","bac","bca","cab","cba"]限制:1 <= s 的长度 <= 8思路:大问题分解为小问题,字符串的长度为len,固定当前字符,则当前字符固定时,字符串的全排列为剩下的len-1个字符的全排列。一直递归下去,遇到最后一个字符,保存当前字符串。因为字符会重复,所以要做一个判断,如果当前位置已经固原创 2021-10-25 13:35:15 · 74 阅读 · 0 评论 -
顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。示例 1:输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]输出:[1,2,3,6,9,8,7,4,5]示例 2:输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]输出:[1,2,3,4,8,12,11,10,9,5,6,7]限制:0 <= matrix.length <= 1000 <= matrix[i].length <= 10原创 2021-09-14 11:40:18 · 118 阅读 · 0 评论 -
二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)”思路:最近公共祖先,说明p、q一定在x的左右两侧,或者p、q自己就是x。自顶向下递归,从树的叶子节点开始返回结果,如果包含了p或者q节点,就返回p或者q节点,否则返回nullptr;左右子树都不为空的那个节点就是最近公共祖先。p、q自身为公共祖先的情况:先遍历到了p原创 2021-06-10 11:05:47 · 67 阅读 · 0 评论 -
二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)”思路:从上往下遍历,当节点值在p、q中间时,当前节点就是最近公共祖先TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root->v原创 2021-06-10 09:59:35 · 49 阅读 · 0 评论 -
平衡二叉树
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。思路:写一个辅助函数,求树的最大深度。递归遍历每一个节点,判断左右子树的深度差是否大于1int high(TreeNode* root){ if(!root)return 0; return max(high(root->left),high(root->right))+1;}bool isBalanced(TreeNode* root) {原创 2021-06-09 17:50:02 · 45 阅读 · 0 评论 -
二叉树的深度
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。思路:当前节点的深度为左右子树中深度较大的加1int maxDepth(TreeNode* root) { if(!root)return 0; return max(maxDepth(root->left),maxDepth(root->right))+1; }...原创 2021-06-09 17:40:49 · 36 阅读 · 0 评论 -
二叉搜索树的第K大节点
给定一棵二叉搜索树,请找出其中第k大的节点。思路:因为是二叉搜索树,所以节点值是按左中右,从小到大排列的。直接从最右节点开始遍历,遍历到第k个时,返回节点值。int kthLargest(TreeNode* root, int k) { stack<TreeNode*>st; while(root||!st.empty()){ while(root){ st.push(root);原创 2021-06-09 16:58:12 · 96 阅读 · 0 评论 -
序列化二叉树
实现两个函数,分别用来序列化和反序列化二叉树。分析题目:序列化没有任何要求,但是要能根据序列化的字符串重新构造这棵树。思路:利用了stringstream,先递归序列化左子树,再递归序列化右子树。递归并不难理解,收获最大的还是了解了stringstream的用法string serialize(TreeNode* root) { stringstream out; return helper1(root,out); } string helper1(T原创 2021-06-09 16:39:59 · 54 阅读 · 0 评论 -
二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径思路:这里的路径是指根节点到叶子节点。定义一个辅助函数,递归遍历树;遍历到的节点,若不为空,则将节点值加入当前路径;判断节点是否为叶子节点,若不是,递归遍历子节点,若是且target==root->val,将当前路径放入结果中。遍历完当前节点之后的所有节点,当前节点pop()出路径 vector<vector<int>>res; vo原创 2021-06-08 13:27:30 · 51 阅读 · 0 评论 -
从上到下打印二叉树 Ⅲ
实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。思路:还是二叉树的层序遍历,设根节点在第0层,则偶数层是从左到右打印,奇数层是从右到左打印。遍历树的方式不变,用队列,每一层从左到右遍历;在奇数层做一个判断,如果是奇数层,每个节点插入到数组的最前面,或者一层都插入完之后对数组做一个翻转vector<vector<int>> levelOrder(TreeNode* root) {原创 2021-06-08 10:58:15 · 98 阅读 · 0 评论 -
从上到下打印二叉树 Ⅱ
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。思路:每层要单独打印到一行,所以在开始遍历当前层的时候记录当前层的节点数量。每遍历完一层,把结果存到二维数组中vector<vector<int>> levelOrder(TreeNode* root) { if(!root)return {}; vector<vector<int>>res; queue<TreeNode*&g原创 2021-06-08 09:35:25 · 56 阅读 · 0 评论 -
对称的二叉树
对称的二叉树实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的思路:因为二叉树是对称的,所以每个节点有一个镜像节点,如:节点a和b是对称的,则满足:1.a的值等于b的值2.a的左子节点和b的右子节点是对称的、a的右子节点和b的左子节点是对称的 bool helper(TreeNode* a,TreeNode *b){ if(!a&&!b)return true; if(!a||!b)return false;原创 2021-06-07 17:58:09 · 58 阅读 · 0 评论 -
完成一个函数,输入一个二叉树,该函数输出它的镜像
完成一个函数,输入一个二叉树,该函数输出它的镜像思路:递归遍历树,对每个节点交换左右节点可以先交换左右节点再递归,也可以先递归再交换左右节点 void helper(TreeNode* root){ if(!root)return; TreeNode* tmp=root->left; root->left=root->right; root->right=tmp; helper(root-&g原创 2021-06-05 13:36:13 · 150 阅读 · 0 评论 -
输入两棵二叉树A和B,判断B是不是A的子结构
输入两棵二叉树A和B,判断B是不是A的子结构约定空树不是任意一个树的子结构B是A的子结构, 即 A中有出现和B相同的结构和节点值。写一个辅助函数 bool isSame(TreeNode* a,TreeNode* b),判断从a节点开始,是否包含树b从上往下遍历树的所有节点,每个节点都和树b进行一次对比 bool isSame(TreeNode* a,TreeNode* b){ if(!b)return true; if(!a)return false;原创 2021-06-05 13:22:01 · 165 阅读 · 0 评论 -
从上往下打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印。对本题的理解是层序遍历二叉树。用队列来保存二叉树的节点,先将树的根节点插入队列当队列不为空时一直执行一下操作:从队列中取出节点,将节点的值存入vector若左子树不为空,将左子树插入队列若右子树不为空,将右子树插入队列class Solution {public: vector<int> PrintFromTopToBottom(TreeNode* root) { vector<int>res原创 2020-09-20 13:30:49 · 769 阅读 · 0 评论