![](https://img-blog.csdnimg.cn/20201014180756724.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指Offer
.
执著者√
!
展开
-
树中两个结点的最低公共祖先
class Solution {public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root) return NULL; if(root == p || root == q) return root; auto left = lowestCommonAncestor(root->left,p,q); aut.原创 2021-07-27 11:33:04 · 70 阅读 · 0 评论 -
把字符串转换成整数(模拟)
C++代码:class Solution {public: int strToInt(string str) { int k = 0, n = str.size(); if(!n) return 0; long long res = 0,p = 1; while(str[k] == ' ') k++; if(str[k] == '+') k++; else if(str[k] == '-') p =.原创 2021-07-27 11:12:04 · 63 阅读 · 0 评论 -
构建乘积数组(前后缀分解)
给定一个数组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]。不能使用除法。样例输入:[1, 2, 3, 4, 5]输出:[120, 60, 40, 30, 24]思考题:能不能只使用常数空间?(除了输出的数组之外)算法:正常可以这样求但是不能用除法,那么先让B[i] = 前i - 1的乘积,然后再把后边i + 1 到n的乘积乘上,用一个变量p来存储前i-1的个数原创 2021-07-27 11:04:26 · 127 阅读 · 0 评论 -
数值的整数次方(快速幂)
实现函数double Power(double base, int exponent),求base的 exponent次方。不得使用库函数,同时不需要考虑大数问题。只要输出结果与答案的绝对误差不超过 10−2 即视为正确。注意:不会出现底数和指数同为0的情况当底数为0时,指数一定为正样例1输入:10 ,2输出:100样例2输入:10 ,-2输出:0.01class Solution {public: double Power(double base, int expon原创 2021-07-26 23:54:21 · 89 阅读 · 0 评论 -
不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用 +、-、×、÷ 四则运算符号。样例输入:num1 = 1 , num2 = 2输出:3class Solution {public: int add(int num1, int num2){ while(num2){ int sum = num1 ^ num2;//先算两个数的和 int carry = (num1 & num2)<<1; //两个数的进位原创 2021-07-26 23:46:13 · 53 阅读 · 0 评论 -
求1+2+…+n
求 1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 (A?B:C)。样例输入:10输出:55class Solution {public: int getSum(int n) { int res = n; n > 0 && (res += getSum(n-1)); return res; }};...原创 2021-07-26 23:19:34 · 80 阅读 · 0 评论 -
股票的最大利润(贪心,线性扫描)
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖 一次 该股票可能获得的利润是多少?例如一只股票在某些时间节点的价格为 [9,11,8,5,7,12,16,14]。如果我们能在价格为 5 的时候买入并在价格为 16 时卖出,则能收获最大的利润 11。样例输入:[9, 11, 8, 5, 7, 12, 16, 14]输出:11算法:枚举在第i天卖出,用一个变量来记录前i天中最小的值,每次取差的max。C++代码:class Solution {public: int max原创 2021-07-26 23:12:45 · 59 阅读 · 0 评论 -
圆圈中最后剩下的数字(约瑟夫问题)
0,1,…,n−1 这 n 个数字 (n>0) 排成一个圆圈,从数字 0 开始每次从这个圆圈里删除第 m 个数字。求出这个圆圈里剩下的最后一个数字。样例输入:n=5 , m=3输出:3循环队列:class Solution {public: int lastRemaining(int n, int m){ queue<int> q; for(int i = 0; i < n; i++) q.push(i); int原创 2021-07-26 22:53:27 · 130 阅读 · 0 评论 -
扑克牌的顺子
1、排序,然后找到不是0的最小数2、判断是否有重复数,如果有重复数一定不能组成顺子3、最大数 - 最小数 <= 4 ,缺的可以用0补;class Solution {public: bool isContinuous( vector<int> nums ) { if(nums.empty()) return false; sort(nums.begin(),nums.end()); int k = 0; wh.原创 2021-07-26 14:13:25 · 147 阅读 · 0 评论 -
骰子的点数(线性DP)
暴力:class Solution {public: vector<int> res; vector<int> numberOfDice(int n) { res = vector<int>(6*n+1,0); dfs(0,n,0); return vector<int>(res.begin()+n,res.end()); } void dfs(int k,int .原创 2021-07-26 13:47:26 · 99 阅读 · 0 评论 -
滑动窗口的最大值(单调队列)
给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组 [2,3,4,2,6,2,5,1] 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,它们的最大值分别为 [4,4,6,6,6,5]。注意:数据保证 k 大于 0,且 k 小于等于数组长度。样例输入:[2, 3, 4, 2, 6, 2, 5, 1] , k=3输出: [4, 4, 6, 6, 6, 5]class Solution {public: vector<int> maxInWi原创 2021-07-26 12:59:50 · 47 阅读 · 0 评论 -
数字在排序数组中出现的次数(二分)
统计一个数字在排序数组中出现的次数。例如输入排序数组 [1,2,3,3,3,3,4,5] 和数字 3,由于 3 在这个数组中出现了 4 次,因此输出 4。样例输入:[1, 2, 3, 3, 3, 3, 4, 5] , 3输出:4暴力:O(n)class Solution {public: int getNumberOfK(vector<int>& nums , int k) { int res = 0; for(auto x : n原创 2021-07-24 16:26:19 · 71 阅读 · 0 评论 -
两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。当不存在公共节点时,返回空节点。样例给出两个链表如下所示:A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3输出第一个公共节点c1算法:让p和q分别指向A链表和B链表的头开始走,如果p为空那么就接着从B链表的头开始走,q为从就从A链表的头开始走,总长度都原创 2021-07-24 16:06:45 · 101 阅读 · 0 评论 -
数组中的逆序对
在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。样例输入:[1,2,3,4,5,6,0]输出:6双重循环O(N^2)写法:class Solution {public: int inversePairs(vector<int>& nums) { int res = 0; for(int i = 0; i < nums.size(); i++)原创 2021-07-24 15:43:01 · 48 阅读 · 0 评论 -
字符流中第一个只出现一次的字符
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符 go 时,第一个只出现一次的字符是 g。当从该字符流中读出前六个字符 google 时,第一个只出现一次的字符是 l。如果当前字符流没有存在出现一次的字符,返回 # 字符。样例输入:“google”输出:“ggg#ll”解释:每当字符流读入一个字符,就进行一次判断并输出当前的第一个只出现一次的字符。算法:用哈希表统计所有字符出现的次数;用一个队列维护字符流,队头前边的字符出现多次的话就可以删掉了,保原创 2021-07-24 15:14:26 · 117 阅读 · 0 评论 -
字符串中第一个只出现一次的字符
在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出b。如果字符串中不存在只出现一次的字符,返回 # 字符。样例:输入:“abaccdeff”输出:‘b’算法:遍历两遍字符串,用一个哈希表来存储每个字符出现的次数,第二次遍历的时候找到只出现一次的字符,如果没有返回#。C++代码:class Solution {public: char firstNotRepeatingChar(string s) { unordered_map<cha原创 2021-07-24 14:38:43 · 782 阅读 · 0 评论 -
丑数(多路归并)
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,但 14 不是,因为它包含质因子 7。求第 n 个丑数的值。样例输入:5输出:5注意:习惯上我们把 1 当做第一个丑数。算法:先观察它们的关系可以发现,会有s2和s1有丑数相同,或者s2和s3有相同的丑数,只要把s1,s2,s3,{1} 取并集;再观察:S1 / 2 = SS2 / 3 = SS3 / 5 = S2,3,5的倍数跟S都是有紧密 联系的,因此需要三个指针i,j,k指原创 2021-07-24 14:30:09 · 53 阅读 · 0 评论 -
最长不含重复字符的子字符串(双指针)
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含从 a 到 z 的字符。样例输入:“abcabc”输出:3算法:用一个指针指向前,一个指针指向后,然后用一个哈希表来维护从前到后的两个指针之间的字母保证只出现一次,如果存在某个字母出现了多次,那么将前指针对应的字母在哈希表中删除,并向后移动一位.C++代码:class Solution {public: int longestSubstringWithoutDuplication(st原创 2021-07-24 14:02:27 · 163 阅读 · 0 评论 -
礼物的最大价值(DP)
在一个 m×n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?注意:m,n>0样例:输入:[[2,3,1],[1,7,1],[4,6,1]]输出:19解释:沿着路径 2→3→7→6→1 可以得到拿到最大价值礼物。C++代码:class Solution {public: int get原创 2021-07-24 13:35:12 · 91 阅读 · 0 评论 -
二进制中1的个数(lowbit运算)
输入一个 32 位整数,输出该数二进制表示中 1 的个数。注意:负数在计算机中用其绝对值的补码来表示。样例1输入:9输出:2解释:9的二进制表示是1001,一共有2个1。样例2输入:-2输出:31解释:-2在计算机里会被表示成11111111111111111111111111111110,一共有31个1。class Solution {public: int NumberOf1(int n) { int cnt = 0; while(n原创 2021-07-26 23:54:33 · 235 阅读 · 0 评论 -
机器人的运动范围
地上有一个 m 行和 n 列的方格,横纵坐标范围分别是 0∼m−1 和 0∼n−1。一个机器人从坐标 (0,0) 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格。但是不能进入行坐标和列坐标的数位之和大于 k 的格子。请问该机器人能够达到多少个格子?样例1输入:k=7, m=4, n=5输出:20样例2输入:k=18, m=40, n=40输出:1484解释:当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为原创 2021-07-23 23:52:57 · 145 阅读 · 0 评论 -
斐波那契数列
输入一个整数 n ,求斐波那契数列的第 n 项。假定从 0 开始,第 0 项为 0。(n≤39)样例输入整数 n=5返回 5class Solution {public: int Fibonacci(int n) { if(n == 0) return 0; else if(n == 1) return 1; return Fibonacci(n-1) + Fibonacci(n-2); }};...原创 2021-07-23 23:50:53 · 52 阅读 · 0 评论 -
从尾到头打印链表
输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。返回的结果用数组存储。样例输入:[2, 3, 5]返回:[5, 3, 2]class Solution {public: vector<int> printListReversingly(ListNode* head) { vector<int> res; while(head){ res.push_back(head->val);原创 2021-07-23 23:49:46 · 38 阅读 · 0 评论 -
替换空格.
请实现一个函数,把字符串中的每个空格替换成"%20"。你可以假定输入字符串的长度最大是 1000。注意输出字符串的长度可能大于 1000。样例输入:“We are happy.”输出:“We%20are%20happy.”class Solution {public: string replaceSpaces(string &str) { string res = ""; for(auto s : str) if(s ==原创 2021-07-23 23:48:42 · 64 阅读 · 0 评论 -
把数字翻译成字符串(DP)
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 a,1 翻译成 b,……,11 翻译成 l,……,25 翻译成 z。一个数字可能有多个翻译。例如 12258 有 5 种不同的翻译,它们分别是 bccfi、bwfi、bczi、mcfi 和 mzi。请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。样例输入:“12258”输出:5算法:C++代码:class Solution {public: int getTranslationCount(string s)原创 2021-07-23 23:44:43 · 106 阅读 · 0 评论 -
把数组排成最小的数(全序关系)
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组 [3,32,321],则打印出这 3 个数字能排成的最小数字 321323。样例输入:[3, 32, 321]输出:321323注意:输出数字的格式为字符串。class Solution {public: static bool cmp(int a,int b){ string sa = to_string(a), sb = to_string(b);原创 2021-07-23 23:11:36 · 107 阅读 · 0 评论 -
数字序列中某一位的数字(数位统计)
数字以 0123456789101112131415… 的格式序列化到一个字符序列中。在这个序列中,第 5 位(从 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。请写一个函数求任意位对应的数字。样例输入:13输出:1算法:C++代码:class Solution {public: int digitAtIndex(int n) { //i表示位数 s表示该位数有多少个数 base表示位数起始值 long long i =原创 2021-07-23 22:35:30 · 79 阅读 · 0 评论 -
从1到n整数中1出现的次数(数位统计)
输入一个整数 n,求从 1 到 n 这 n 个整数的十进制表示中 1 出现的次数。例如输入 12,从 1 到 12 这些整数中包含 “1” 的数字有 1,10,11 和 12,其中 “1” 一共出现了 5 次。样例输入: 12输出: 5算法:按位来统计1的个数C++代码:class Solution {public: int numberOf1Between1AndN_Solution(int x) { vector<int> nums;原创 2021-07-23 18:02:55 · 264 阅读 · 0 评论 -
连续子数组的最大和(贪心)
输入一个 非空 整型数组,数组里的数可能为正,也可能为负。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n)。样例输入:[1, -2, 3, 10, -4, 7, 2, -5]输出:18算法:s表示的以前一个数结尾的最大和s < 0 , s = 0, 一个小于0的数加x不可能使得结果变得更大s > 0, s = s + xs = 0,s = s + xC++代码:class Solution {public: i原创 2021-07-23 17:13:06 · 159 阅读 · 0 评论 -
数据流中的中位数(堆)
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。样例输入:1, 2, 3, 4输出:1,1.5,2,2.5解释:每当数据流读入一个数据,就进行一次判断并输出当前的中位数。算法一:用STL,维护一个有序的vector数组,每次插入一个数时,先用lower_bound找到第一个大于等于x的位置,然后插入;class Solution {public:原创 2021-07-23 17:09:32 · 157 阅读 · 0 评论 -
最小的k个数
输入 n 个整数,找出其中最小的 k 个数。注意:输出数组内元素请按从小到大顺序排序;数据范围1≤k≤n≤1000样例输入:[1,2,3,4,5,6,7,8] , k=4输出:[1,2,3,4]堆O(klogk):class Solution {public: vector<int> getLeastNumbers_Solution(vector<int> input, int k) { priority_queue<int>原创 2021-07-22 23:43:19 · 58 阅读 · 0 评论 -
数组中出现次数超过一半的数字(脑洞题)
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。假设数组非空,并且一定存在满足条件的数字。思考题:假设要求只能使用 O(n) 的时间和额外 O(1) 的空间,该怎么做呢?样例输入:[1,2,1,1,3]输出:1算法:题目规定这个数字次数一定超过数组长度一半,如果说这个数字和其他数字一对一抵消掉,那么至少还会剩下一个;用个cnt来记录val的个数cnt == 0 ,val = x,一个新的数cnt != 0 且 val != x, cnt–;最后val的值就是答案C原创 2021-07-22 23:29:21 · 34 阅读 · 0 评论 -
数字排列.
输入一组数字(可能包含重复数字),输出其所有的排列方式。样例输入:[1,2,3]输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]递归版:去重全排列class Solution {public: vector<vector<int>> res; vector<原创 2021-07-22 23:04:17 · 91 阅读 · 0 评论 -
序列化二叉树(多种方式实现)
请实现两个函数,分别用来序列化和反序列化二叉树。您需要确保二叉树可以序列化为字符串,并且可以将此字符串反序列化为原始树结构。样例你可以序列化如下的二叉树 8 / \ 12 2 / \ 6 4为:"[8, 12, 2, null, null, 6, 4, null, null, null, null]"注意:以上的格式是AcWing序列化二叉树的方式,你不必一定按照此格式,所以可以设计出一些新的构造方式。层序遍历建树:class Solutio原创 2021-07-22 22:30:46 · 986 阅读 · 1 评论 -
二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。注意:需要返回双向链表最左侧的节点。例如,输入下图中左边的二叉搜索树,则输出右边的排序双向链表。每次返回左边和右边的一对数,然后连接起来;C++代码:class Solution {public: TreeNode* convert(TreeNode* root) { if(!root) return NULL; auto res原创 2021-07-22 15:01:08 · 76 阅读 · 0 评论 -
复杂链表的复刻
请实现一个函数可以复制一个复杂链表。在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个额外的指针指向链表中的任意结点或者null。注意:函数结束后原链表要与输入时保持一致。算法:先给每一个节点后面都复制一个节点;让复制节点的random指向原有的节点random的指向;把复制出来的节点串起来C++代码:/** * Definition for singly-linked list with a random pointer. * struct ListNode原创 2021-07-22 14:16:02 · 78 阅读 · 0 评论 -
二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。样例给出二叉树如下所示,并给出num=22。 5 / \ 4 6 / / \ 12 13 6 / \ / \9 1 5 1输出:[[5,4,12,1],[5,6,6,5]]算法:dfs,树的遍历C++代码:class Solution {public: vector<ve原创 2021-07-22 13:32:25 · 70 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。样例输入:[4, 8, 6, 12, 16, 14, 10]输出:true算法:二叉搜索树递归定义,左子树比根小,右子树比根大,因此根据后序遍历的顺序,左右根,不断划分左右子树,判断是否符合二叉搜索树的定义;C++代码:class Solution {public: vector<int> seq; bool ve原创 2021-07-22 13:17:47 · 56 阅读 · 0 评论 -
之字形打印二叉树
请实现一个函数按照之字形顺序从上向下打印二叉树。即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。样例输入如下图所示二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null] 8 / \ 12 2 / \ 6 4输出:[[8], [2, 12], [6, 4]]算法:二叉树的层序遍历,用d来标记,如果是奇数行,先将ans翻转,再存入res;原创 2021-07-22 12:59:45 · 100 阅读 · 0 评论 -
分行从上往下打印二叉树
从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。样例输入如下图所示二叉树[8, 12, 2, null, null, 6, null, 4, null, null, null] 8 / \ 12 2 / 6 / 4输出:[[8], [12, 2], [6], [4]]算法:跟二叉树的层序遍历步骤一样,这里只需要先统计这一层有多少个节点;C++代码:class Solution {public: vecto原创 2021-07-22 13:00:01 · 61 阅读 · 0 评论