![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指Offer
nirvana · rebirth
NIRVANA & REBIRTH
展开
-
剑指 Offer 38. 字符串的排列
AC-Codeclass Solution {private: bool nextPermutation(string& s) { // 首先从后向前查找第一个顺序对 (i,i+1),满足 a[i] < a[i+1]。这样「较小数」即为 a[i]。此时 [i+1,n) 必然是下降序列。 int i = s.size() - 2; while (i >= 0 && s[i] >= s[i + 1]) { .原创 2021-09-07 15:17:57 · 187 阅读 · 0 评论 -
剑指Offer——JZ32.把数组排成最小的数【贪心】
题目传送门题解AC-Code很简单的排序题不过实际上,对于两个数a,b,并不需要我们分析什么情况下a在前或者在后。直接用结果去判定即可class Solution {public: string PrintMinNumber(vector<int> numbers) { sort(numbers.begin(), numbers.end(), cmp); string ans; for(int i = 0; i &l原创 2020-07-01 19:40:09 · 207 阅读 · 0 评论 -
剑指Offer——JZ33.丑数
题目传送门题解自底向上的思维方式,用乘法去升序得到每一个丑数AC-Codeclass Solution {public: int GetUglyNumber_Solution(int index) { if(index <= 0) return 0; vector<int> ans(index); int p2 = 0, p3 = 0, p5 = 0; ans[0] = 1;原创 2020-06-29 09:19:55 · 217 阅读 · 0 评论 -
剑指Offer——JZ34.第一个只出现一次的字符【bitset】
题目传送门题解bitset占用内存更小。进阶题目:JZ54.字符流中第一个不重复的字符AC-Codeclass Solution {public: int FirstNotRepeatingChar(string str) { bitset<128> bs1, bs2; for(int i = 0; i < str.length(); ++i) { if(bs1[str[i]])原创 2020-06-27 14:30:30 · 200 阅读 · 0 评论 -
剑指Offer——JZ36.两个链表的第一个公共结点【思维】
题目传送门题解AC-Code/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { auto pa = pHead1, pb =原创 2020-06-26 13:44:51 · 209 阅读 · 0 评论 -
剑指Offer——JZ37.数字在排序数组中出现的次数【二分】
题目传送门题解遍历一遍真的是太不优美(sb)了有序数组嘛,闭着眼睛都知道是二分→_→找到两个位置第一个>=k的位置第一个>k的位置AC-Codeclass Solution {public: int GetNumberOfK(vector<int> data ,int k) {// return solve(data, k); auto lindex = lower_bound(data.begin(),原创 2020-06-26 13:27:29 · 246 阅读 · 0 评论 -
剑指Offer——JZ38.二叉树的深度
题目传送门题解sb题,不多bbAC-Code/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { }};*/class Solution {public: int TreeDepth(TreeNode* pRoot) { if(!pRoot)原创 2020-06-26 12:38:08 · 225 阅读 · 0 评论 -
剑指Offer——JZ39.平衡二叉树【DFS】
题目传送门题解所求即为:是否有节点的左右子树高度差 > 1树上dfs跑一下即可AC-Codeclass Solution {public: bool IsBalanced_Solution(TreeNode* pRoot) { if(!pRoot) return true; return dfs(pRoot) != -1; } int dfs(TreeNode* now) { if(!now)原创 2020-06-26 12:32:59 · 208 阅读 · 0 评论 -
剑指Offer——JZ40.数组中只出现一次的数字【位运算】
题目传送门题解我们知道 aaa ^ a=0a=0a=0那么把所有数都异或一遍,得到ret就是 A ^ B的值A 异或 B的结果,代表了A和B在哪些位上是不一样的。那么我们可以随便找一个ret上为1的位,在这一位上,A和B是不同的。那么我们可以根据这一位,讲数组分为两组,然后每一组,异或一遍,就可以得到所求的两个数了。AC-Codeclass Solution {public: void FindNumsAppearOnce(vector<int> data,原创 2020-06-25 23:54:25 · 152 阅读 · 0 评论 -
剑指Offer——JZ41.和为S的连续正数序列【滑动窗口】【√N复杂度数学解法】
题目传送门题解暴力直接gun粗对于连续区间的问题,前缀和滑动窗口都是不错的方案。滑动窗口的解法的时间复杂度很显然是 O(N)O(N)O(N),实际时间复杂的可以常数降低至 O(N2)O(\frac{N}{2})O(2N)前缀的话,一遍求前缀数组,然后按照滑动窗口的方式。其实最终都是滑动窗口的思维方式,因为O(N2)O(N^2)O(N2) 枚举起终点的解法太垃圾了还有一种官方没有的解法,时间复杂度可以降低至 O(N)O(\sqrt{N})O(N):如果长度为 nnn 的连续整数和原创 2020-06-25 14:11:46 · 245 阅读 · 0 评论 -
剑指Offer——JZ42.和为S的两个数字【二分】
题目传送门题解二分答案对于 a<b<c<d,a+d==b+ca<b<c<d,a+d==b+ca<b<c<d,a+d==b+c 时,一定有 a∗d<b∗ca*d<b*ca∗d<b∗c所以输出乘积最小的只是个幌子,第一次找到的二分答案就是最优解AC-Codeclass Solution {public: vector<int> FindNumbersWithSum(vector<int&g原创 2020-06-25 11:30:28 · 265 阅读 · 0 评论 -
剑指Offer——JZ43.左旋转字符串
题目传送门题解官方给的题解当 n>str.length()n>str.length()n>str.length() 的时候,就不处理了。这样应该是不对的,对于 n>str.length()n>str.length()n>str.length(),按照题意是可以进行循环左移的。取余即可AC-Codeclass Solution {public: string LeftRotateString(string str, int n) {原创 2020-06-25 11:21:48 · 269 阅读 · 0 评论 -
剑指Offer——JZ44.翻转单词顺序列
题目传送门题解题目没让对空格进行额外处理,只是反转内容。但是很多题解却处理了额外的空格,应该是不对的。如果不要多余空格,可以使用 stringstreamstringstreamstringstream 类AC-Codeclass Solution {public: string ReverseSentence(string str) { // 只反转,保留原空格位置、数量。 if(str.empty()) return str;原创 2020-06-25 11:14:12 · 317 阅读 · 0 评论 -
剑指Offer——JZ45.扑克牌顺子【排序 & 思维】
题目传送门题解排序然后随便搞一下即可AC-Codeclass Solution {public: bool IsContinuous( vector<int> numbers ) { if(numbers.empty()) return false; sort(numbers.begin(), numbers.end()); int zeronums = 0; // 万能牌的个数 for(i原创 2020-06-22 16:31:18 · 340 阅读 · 0 评论 -
剑指Offer——JZ46.孩子们的游戏(圆圈中最后剩下的数)【递归 | 迭代】
题目传送门题解解法一:暴力O(n2)O(n^2)O(n2)解法二:递归设f[n,m]f[n,m]f[n,m]表示题意所求。则首先明确f[1,m]=0f[1,m]=0f[1,m]=0(一个人肯定就是自己了)采用自底向上的方式,设x=f[n−1,m]x=f[n-1,m]x=f[n−1,m]当前长度为 nnn,那么本次会删除 n%mn\%mn%m 的位置,变成长度为 n−1n-1n−1。而我们已经知道了,长度为 n−1n-1n−1 的时候,最后一名所在位置是 xxx所以 f[n,m]=(m原创 2020-06-22 16:17:33 · 312 阅读 · 0 评论 -
剑指Offer——JZ47.求1+2+3+...+n【使用&&特性控制递归边界】
题目传送门题解直接通项公式即可,不过不够亮点,循环肯定是不允许的,如果使用递归,一般都需要if来控制边界可以使用 && 的特性(如果前面false,则不判断后面)来控制递归边界AC-Codeclass Solution {public: int Sum_Solution(int n) { n > 1 && (n += Sum_Solution(n-1)); return n; }};...原创 2020-06-22 15:44:38 · 273 阅读 · 0 评论 -
剑指Offer——JZ48.不用加减乘除法做加法【二进制】
题目传送门题解在二进制运算中,对于某一位来讲:a∧b:表示a+b的本位a \wedge b:表示a+b的本位a∧b:表示a+b的本位a & b:表示a+b应该进的位a\ \&\ b:表示a+b应该进的位a & b:表示a+b应该进的位a & b<<1:表示进位之后a\ \&\ b <<1:表示进位之后a & b<<1:表示进位之原创 2020-06-22 15:36:43 · 267 阅读 · 0 评论 -
剑指Offer——JZ49.把字符串转换成整数
题目传送门题解注意正负问题面试时,可以选取鲁棒性更好的实现AC-Codeclass Solution {public: int StrToInt(string str) { int num = 0; bool flag = true; // true:+, false:- int start = 0; if(str[0] == '+' || str[0] == '-') { flag原创 2020-06-22 15:23:22 · 267 阅读 · 0 评论 -
剑指Offer——JZ50.数组中重复的数字【思维】
题目传送门题解最简单的方法是hash或者set,遍历即可由于所有数字范围都是 [0,n−1][0, n-1][0,n−1]所以每个数字都有属于自己的位置那么就把不在自己位置的数每个数方到自己的位置,如果该位置已经占用了,就说明有重复。AC-Codeclass Solution {public: // Parameters: // numbers: an array of integers // length:原创 2020-06-21 21:24:41 · 201 阅读 · 0 评论 -
剑指Offer——JZ51.构造乘积数组【前后缀数组】
题目传送门题解区间线性问题,直接考虑前后缀即可分别计算前缀后缀乘积和,即可线性复杂度AC-Codeclass Solution {public: vector<int> multiply(const vector<int>& A) { vector<int> B(A.size(), 1); for (int i = 1; i < A.size(); ++i) B[i]原创 2020-06-19 17:02:38 · 198 阅读 · 0 评论 -
剑指Offer——JZ52.正则表达式匹配【递归 | DP】
题目传送门AC-Code#include <regex>class Solution {public: bool match(char* str, char* pattern) { if(str == NULL || pattern == NULL) return false; return ans3(str, pattern); } bool ans1(char* str, char* pattern) {原创 2020-06-19 16:45:45 · 267 阅读 · 1 评论 -
剑指Offer——JZ53.表示数值的字符串【正则表达式】
题目传送门题解AC-Code#include <regex>class Solution {public: bool isNumeric(char* string) { if(!string) return false; std::regex reg("^[-+]?\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?$"); return regex_match(string, reg);原创 2020-06-18 15:17:26 · 198 阅读 · 0 评论 -
剑指Offer——JZ54.字符流中第一个不重复的字符【哈希+队列】
题目传送门题解AC-Codeclass Solution {public: //Insert one char from stringstream queue<char> q; unordered_map<char, int> mp; void Insert(char ch) { // 如果是第一次出现, 则添加到队列中 if (mp.find(ch) == mp.end())原创 2020-06-17 20:56:13 · 231 阅读 · 0 评论 -
剑指Offer——JZ55.链表环的入口结点【快慢指针】
题目传送门题解**解法一:**记录走过的结点,遇到走过的判定为有环解法二:AC-Code/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* EntryNodeOfLoop(ListNode* pHead) {原创 2020-06-17 10:11:18 · 200 阅读 · 0 评论 -
剑指Offer——JZ56.删除链表中重复的结点【前驱后继指针】
题目传送门题解注意重复的结点一个也不保留因为第一个结点也可能是重复的,所以预先创建一个头,方便代码书写,更美观。AC-Code/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* deleteDuplication(L原创 2020-06-16 17:36:48 · 201 阅读 · 0 评论 -
剑指Offer——JZ57.二叉树的下一个结点【中序遍历】
题目传送门题解找到跟结点,中序遍历即可AC-Code/*struct TreeLinkNode { int val; struct TreeLinkNode *left; struct TreeLinkNode *right; struct TreeLinkNode *next; TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) { }};原创 2020-06-16 16:27:41 · 165 阅读 · 0 评论 -
剑指Offer——JZ58.对称的二叉树【DFS】
题目传送门题解如果对称,一定满足:L->val == R->valL->left->val == R->right->valL->right->val == R->left->val递归传入对称的两个点,然后对称的递归下去AC-Code/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right;原创 2020-06-16 15:30:55 · 184 阅读 · 0 评论 -
剑指Offer——JZ59.按之字形顺序打印二叉树【BFS】
题目传送门题解和JZ60.把二叉树打印成多行是一样的,只不过偶数行逆序。偶数行的时候多个反转步骤即可AC-Code/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { }};*/class Solution {pu原创 2020-06-16 15:19:29 · 189 阅读 · 0 评论 -
剑指Offer——JZ60.把二叉树打印成多行【BFS】
题目传送门题解AC-Codeclass Solution {public: vector<vector<int> > Print(TreeNode* pRoot) { vector<vector<int>> ret; queue<TreeNode*> q; if(pRoot) q.push(pRoot); while (!q.empty()) {原创 2020-06-14 00:06:11 · 206 阅读 · 0 评论 -
剑指Offer——JZ61.序列化二叉树(先序最好写)
题目传送门题解首先考虑写先序遍历。遇到 NULLNULLNULL 写入 "#""\#""#"遇到非空,写入 "i,""i,""i,"细节见代码考虑中序、后序遍历:对于这样一棵树 4 2 6 1 3 5 7在先序的时候,我们每次先访问根,然后才是左和右,这样没什么毛病但是中序、后序的时候,就会出现问题按照这个数,我们序列化之后,一定是 # 开头,那么就需要很多的特判来避免歧义,比较复杂。所以最好使用先序遍历序列化AC-Codeclass Solut原创 2020-06-13 13:35:19 · 214 阅读 · 0 评论 -
剑指Offer——JZ62.二叉搜索树的第k个结点【中序遍历】
题目传送门题解中序遍历记格数即可AC-Code/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { }};*/class Solution {public: TreeNode* KthNode(TreeNod原创 2020-06-13 11:06:35 · 147 阅读 · 0 评论 -
剑指Offer——JZ63.数据流中的中位数【堆】
题目传送门题解既然只要中位数,那么可以把 nnn 个数分成两部分,小的那部分维护最大值,大的那部分维护最小值。这样中位数可以在 O(1)O(1)O(1) 时间复杂度内求解出来。基于这样的思想,可以维护两个堆即可。由于流式样例,所以对于每次来的数,需要判断应该放在大的那部分还是小的那部分,然后平衡两个堆数量AC-Codeclass Solution {private: priority_queue<int> min_q; // 偏小的数,维护这里的最大值,大顶堆原创 2020-06-10 20:15:24 · 193 阅读 · 0 评论 -
剑指Offer——JZ64.滑动窗口的最大值【单调队列】
题目传送门题解可以暴力求解,时间复杂度 O(nk)O(nk)O(nk)考虑 iii 和 i+1i+1i+1 共存的区间:如果 num[i]<=num[i+1]num[i]<=num[i+1]num[i]<=num[i+1],那么无须考虑 num[i]num[i]num[i]如果 num[i]>num[i+1]num[i]>num[i+1]num[i]>num[i+1],那么需要保留 num[i+1]num[i+1]num[i+1] ,因为,当 num[i原创 2020-06-04 18:36:21 · 214 阅读 · 0 评论 -
剑指Offer——JZ65.矩阵中的路径【DFS】
题目传送门题解使用 DFS + 回溯AC-Codeclass Solution { int dx[4] = { 0, 0, 1, -1 }; int dy[4] = { 1, -1, 0, 0 }; bool** vis;public: bool hasPath(char* matrix, int rows, int cols, char* str) { vis = new bool* [rows]; for (int i = 0; i < rows; ++i)原创 2020-06-04 15:31:35 · 196 阅读 · 0 评论 -
剑指Offer——JZ66.机器人的运动范围【BFS | DFS】
题目传送门样例:5,10,10输出:21题解直接BFS或者DFS即可。注意:memset不能对动态创建的二维数组初始化,因为每次 new 或者 malloc 的时候,分配的不是连续地址,每行的元素地址连续,各行之间地址不保证连续。同样可以使用一维数组表示二维数组bool *vis;vis = new bool[sizeof(bool) * rows * cols];memset(vis, false, sizeof(bool) * rows * cols);vis[i * cols原创 2020-06-04 13:22:31 · 206 阅读 · 0 评论 -
剑指Offer——JZ67.剪绳子【DP | 贪心】
题目传送门题解动态规划:对于任意 nnn,分解为 f1,f2,f3...fkf_1,f_2,f_3 ... f_kf1,f2,f3...fk。对于任意 fi,i∈[1,k]f_i,i∈[1, k]fi,i∈[1,k] 继续拆分后,最后都是乘积关系,所以满足无后效性,可以使用动态规划解决。设 dp[i]dp[i]dp[i] 为长度为 iii 的绳子分解最大值。那么状态转移方程: dp[i]=max(dp[i],dp[i−j]∗dp[j]),d∈[1,i/2]dp[i] = max(原创 2020-06-04 01:08:49 · 197 阅读 · 0 评论