![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offer
ziggy7
这个作者很懒,什么都没留下…
展开
-
剑指offer Leetcode 38. ?字符串的排列
解法:回溯思想:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/mian-shi-ti-38-zi-fu-chuan-de-pai-lie-hui-su-fa-by/固定用于排列方案的去重,set用于每一位的去重(字符串本身有重复)代码class Solution {public: vector<string>res; vector<string> permuta.原创 2021-04-01 11:11:10 · 71 阅读 · 0 评论 -
剑指offer Leetcode 排列、组合、子集总结
解法一:DFS思想:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/mian-shi-ti-13-ji-qi-ren-de-yun-dong-fan-wei-dfs-b/其中证明了只要往右和下走就能访问所有可达解。复杂度分析:时间复杂度:O(MN),最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为O(MN)空间复杂度:O(MN)代码:class Solution {public.原创 2021-03-19 16:20:50 · 109 阅读 · 0 评论 -
剑指offer Leetcode 12.矩阵中的路径
回溯法:思想https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/solution/mian-shi-ti-12-ju-zhen-zhong-de-lu-jing-shen-du-yo/其中的ppt很清楚复杂度递归的空间复杂度是递归的深度*每次压栈所需的空间个数代码class Solution {public: bool exist(vector<vector<char>>& .原创 2021-03-19 16:20:06 · 57 阅读 · 0 评论 -
剑指offer Leetcode 59 - II. 队列的最大值
解法:思想: 本质是求滑动窗口最大值的问题。队列可以看成是一个滑动窗口,入队就是将窗口的右边界右移,出队就是将窗口的左边界右移。复杂度: 操作均摊都是O(1)代码:class MaxQueue {public: //正常的队列 queue<int>queue; //非严格递减的双端队列,头部就是最大值 deque<int>deque; MaxQueue() { } int max_value() .原创 2021-03-19 16:19:30 · 63 阅读 · 0 评论 -
剑指offer Leetcode 59 - I. 滑动窗口的最大值(deque单调队列)
解法1:暴力法思想: 遍历每个滑动窗口,找出其中的最大值复杂度: ●时间:O((N - k + 1)k) = O(Nk),每个窗口k个数,总共有N - k + 1个窗口 ●空间:解法2:单调队列https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/solution/mian-shi-ti-59-i-hua-dong-chuang-kou-de-zui-da-1-6/思想: 用deque维护一.原创 2021-03-19 16:17:06 · 117 阅读 · 0 评论 -
剑指offer Leetcode 57 - II. 和为s的连续正数序列
解法:滑动窗口思想: 维护一个左闭右闭的滑动窗口,左右边界只能增加,不能减小。根据和与target的关系来移动left与right,右移right是新增一个数,右移left是减去一个数。复杂度: ●时间:O(N),遍历 ●空间:O(1)代码注意点(不看注释想出原因):●while循环的条件为?●left和right初值?●left和right增和加/减的顺序●找到一组答案后怎么继续遍历?代码:注意右移right是先增再加,右移left是先减再增class Solution .原创 2021-03-19 16:16:22 · 53 阅读 · 0 评论 -
剑指offer Leetcode 53-II 0~n - 1中缺失的数字
解法:二分思想: ●初始化:区间[0, nums.size() - 1] ●循环二分: 1.计算中点mid 2.如果nums[mid] == mid,则 “右子数组的首位元素” 一定在[mid + 1, right]中,所以left = mid + 1 3.如果nums[mid] != mid,则“左子数组的末位元素” 一定在[left, mid - 1]中,所以right = mid - 1 ●返回值:跳出时,left和right分别指向"右子数组的首位元素"和"左子.原创 2021-03-19 16:14:50 · 62 阅读 · 0 评论 -
剑指offer Leetcode 53 - I. 在排序数组中查找数字 I
解法:二分法思想: 二分查找通常用于查找单个数,所以用在此题需要改变一下。 定义一个函数,返回target右边的数的索引,结果可以通过find(target) - find(target - 1)得到过程: ●初始化:在区间[0, nums.size() - 1]中查找,令left和right为左右边界 ●定义左右区间:左区间小于等于target, 右区间大于target ●循环二分: 1.计算中点mid 2.如果nums[mid] <= target,说明右子数.原创 2021-03-19 16:14:19 · 66 阅读 · 0 评论 -
剑指offer Leetcode 63. 股票的最大利润(买卖一次)
注意: 一定要明确转移方程解法:动态规划思想:●状态定义:●转移方程: 前i日的最大利润 = max(前i - 1日的最大利润, 第i日价格 - 前i日最低价格) dp[i] = max(dp[i - 1], prices[i] - min(prices[0 : i])),前i日最低价格用一个变量来维护我的理解: 前i天的最大利润要么就是第i天不操作,即前i - 1天最大利润。 要么就是第i天操作即卖出●初始状态: dp[0] = 0,即首日利润为0.原创 2021-03-19 16:13:43 · 99 阅读 · 0 评论 -
剑指offer Leetcode 60.n个骰子的点数
解法:动态规划思想: 可以把n个骰子的点数分解为n - 1个骰子的点数加上1个骰子的点数。根据1的概率数组求出2的概率数组,根据2求出3…直到求出n的点数。●状态定义:tmp[]为n个骰子的概率数组,pre[]为n - 1个骰子的概率数组,1个骰子的概率数组显然是6个1/6●初始状态: vectorpre = {1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6};●状态转移方程:tmp[x + y] += pre[x] * num[y];.原创 2021-03-19 16:12:58 · 62 阅读 · 0 评论 -
剑指offer Leetcode 49.丑数
解法:思想:●丑数: 一个丑数乘以2,3,5之后,一定还是一个丑数。●丑数序列: 计算丑数序列其实就是合并三个有序序列。//即丑数序列乘以2,3,5nums2 = {1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 8*2...}nums3 = {1*3, 2*3, 3*3, 4*3, 5*3, 6*3, 8*3...}nums5 = {1*5, 2*5, 3*5, 4*5, 5*5, 6*5, 8*5...}●逻辑 丑数序列乘以2,3,5得到三个序列,这三个序列合.原创 2021-03-19 16:11:22 · 69 阅读 · 0 评论 -
剑指offer Leetcode 47.礼物的最大价值
解法:动态规划(非原地修改)思想: ●状态定义:dp[i][j]为以grid[i - 1][j - 1]为结尾的路径的最大值 ●转移方程:到当前点只能从上面和左边来,所以选两者中最大的。 dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1]; ●初始状态:新建双层vector比grid大一行一列,在上边和左边加了一排0,所以dp[i][j]对应着grid[i - 1][j - 1] ●返回值:返回dp[m].原创 2021-03-17 12:54:34 · 66 阅读 · 0 评论 -
剑指offer Leetcode 46. 把数字翻译成字符串
**一刷12.14 **二刷12.15解法:动态规划思想: ●状态定义:dp[i]代表以Xi为结尾的数字的翻译方案数量 ●转移方程: 若Xi和Xi-1两位数字可以合在一起被翻译,那么dp[i] = dp[i - 1] + dp[i - 2],因为两位连起来翻译和Xi单独翻译得到的结果是完全不同的,所以可以相加。 否则dp[i] = dp[i - 1],必须单独翻译当前位,所以没有变化 ●初始状态:dp[0] = dp[1] = 1,即无数字和第一位数字的翻译方法为1 .原创 2021-03-17 12:53:43 · 63 阅读 · 0 评论 -
剑指offer Leetcode 42.连续子数组的最大和
解法1:贪心思想: 如果当前和为负,就抛弃当前和,从下一个数开始。如果当前和为正,就继续使用。每遇到一个数就更新一次最大和。复杂度: 时间:O(n) 空间:O(1)代码:class Solution {public: int maxSubArray(vector<int>& nums) { int maxsum = INT_MIN; int sum = 0; for(int i : nums){ .原创 2021-03-17 12:52:56 · 51 阅读 · 0 评论 -
剑指offer Leetcode 13. 机器人的运动范围
解法1:贪心class Solution {public: int cuttingRope(int n) { if( n <= 3) return n - 1; long long res = 1; while(n > 4){ n -= 3; res = res * 3 % 1000000007; } return res * n .原创 2021-03-17 12:52:04 · 62 阅读 · 0 评论 -
剑指offer Leetcode 14-I 剪绳子
解法1:动态规划思想:dp[n]代表长度为n的绳子剪完后长度乘积的最大值,长度123不剪比剪要更大,所以不剪,4开始就肯定是剪后>=剪前,所以dp[i] = max(dp[i], dp[j] * dp[i - j]);复杂度时间复杂度:O(n^2),两次循环空间复杂度:dp数组占据O(n)空间代码class Solution {public: int cuttingRope(int n) { //n <= 3时,数字要求至少分为两部分,实际结果的最大值为.原创 2021-03-17 12:51:33 · 87 阅读 · 0 评论 -
剑指offer Leetcode 10.斐波那契数列
解法1:效率低的解法复杂度速度十分缓慢,重复计算太多代码//未考虑溢出和取模class Solution {public: int fib(int n) { if(n <= 0) return 0; if(n == 1) return 1; return fib(n - 1) + fib(n - 2); }};解法2:复杂度:时间复杂度O(n)代码class So.原创 2021-03-17 12:50:34 · 53 阅读 · 0 评论 -
剑指offer Leetcode 10 II.青蛙跳台阶问题
思想:也是斐波那契数列,n级台阶的跳法 = n - 1级的跳法 + n - 2级的跳法。即f(n) = f(n - 1) + f(n - 2),但是要注意起始条件n = 0时为1,n= 1时为1,n = 2时为2原创 2021-03-17 12:49:55 · 50 阅读 · 0 评论 -
剑指offer Leetcode 10 I .斐波那契数列
解法1:效率低的解法复杂度速度十分缓慢,重复计算太多代码//未考虑溢出和取模class Solution {public: int fib(int n) { if(n <= 0) return 0; if(n == 1) return 1; return fib(n - 1) + fib(n - 2); }};解法2:复杂度:时间复杂度O(n)代码class So.原创 2021-03-17 12:49:12 · 59 阅读 · 0 评论 -
剑指offer 17. 打印从1到最大的n位数
Leetcode上的题目简化了,没有意义。题目: 输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999陷阱 这道题看起来很简单,但是要想到会不会n输入太大,n位数用int或者long long都会溢出?也就是说我们需要考虑大数问题。解法一:迭代如何表示出大数? 想到用字符串或者数组表达大数。本题使用字符串来表示。具体流程 将字符串每个字符都初始化为’0’,然后每一次为字符串表示的数字加一,再打印出来。所以需要做两件事:一是在字符串表达的数原创 2021-03-17 12:48:13 · 62 阅读 · 0 评论 -
剑指offer Leetcode 16. 数值的整数次方
解法1:快速幂注意: ●要考虑各种边界条件,如x为0且n为负数的情况,如x为0且n为0的情况。 ●要注意double的判等不能用==思想:https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/solution/mian-shi-ti-16-shu-zhi-de-zheng-shu-ci-fang-kuai-s/有二分法的思想在里面:复杂度: ●时间:二分法思想O(logn) ●空间:常数空间O(1)代码.原创 2021-03-17 12:47:06 · 61 阅读 · 0 评论 -
剑指offer Leetcode 58 - II. 左旋转字符串
解法一:遍历思想: 遍历存到res中复杂度:●时间:O(N)●空间:O(N)代码:class Solution {public: string reverseLeftWords(string s, int n) { string res = ""; for(int i = n; i < s.size(); ++i) res += s[i]; for(int i = 0; i < n; ++i) .原创 2021-02-22 21:08:33 · 115 阅读 · 0 评论 -
剑指offer Leetcode 58 - I. 翻转单词顺序
我的解法:(双指针从左往右遍历,效率差,不使用)思想: 双指针获得每个单词,然后连起来。复杂度: string的相加效率很低缺点: 从左往右遍历时,后面的答案需要添加到字符串左边,所以效率很低。 从右往左遍历时,直接用+=就好代码:class Solution {public: string reverseWords(string s) { if(s.empty()) return ""; int left = ..原创 2021-02-22 21:08:00 · 116 阅读 · 0 评论 -
剑指offer Leetcode 50. 第一个只出现一次的字符
解法1:哈希表思想: 用哈希表(这里直接改进为vector存储,因为只有小写字母)来存储字母出现的次数,然后遍历得到第一个出现一次的数组。复杂度: ●时间:O(N),遍历了两遍数组 ●空间:O(1),vector大小26代码:class Solution {public: char firstUniqChar(string s) { if(s.empty()) return ' '; //26个小写字母 .原创 2021-02-22 21:07:17 · 81 阅读 · 3 评论 -
剑指offer Leetcode 48. 最长不含重复字符的子字符串
解法1:滑动窗口思想: 用set维护一个不重复的滑动窗口,得到以s[right]为结尾的最长无重复子串(即s[left]到s[right])。复杂度: ●时间:O(N),for循环需遍历n次,while循环只有重复才执行,就算最坏情况下全部重复也就执行N次,所以O(N) + O(N) ●空间:O(1),set中最多存储128个数。使用vector效率更高。代码:class Solution {public: int lengthOfLongestSubstring(strin.原创 2021-02-22 21:06:43 · 64 阅读 · 0 评论 -
剑指offer Leetcode 20.表示数值的字符串
思想:字符串的模式代码:class Solution {private: //扫描整数,如果有符号则跳过符号,去扫描无符号整数 //要改变index,记得传引用 bool scanInteger(const string s, int& index){ if(s[index] == '+' || s[index] == '-') ++index; return scanUnsignedInteger(s, i.原创 2021-02-22 21:06:10 · 88 阅读 · 0 评论 -
剑指offer Leetcode 5.替换空格
非原地解法:较为简单。时间复杂度O(n)空间复杂度O(n)class Solution {public: string replaceSpace(string s) { string res; for(string::iterator p = s.begin(); p != s.end(); ++p){ if(*p == ' ') res += "%20"; else .原创 2021-02-22 21:05:18 · 85 阅读 · 0 评论 -
剑指offer Leetcode 9.用两个栈实现队列
class CQueue {public: //s2用来放入值,再把s2的值取出来放入s1就是队列顺序(负负得正) stack<int>s1; stack<int>s2; CQueue() { } //s2直接插入,deleteHead时再把s2放入s1 void appendTail(int value) { s2.push(value); } int deleteHead() .原创 2021-02-22 11:06:57 · 53 阅读 · 0 评论 -
剑指offer Leetcode 31.栈的压入、弹出序列
解法:贪心思想: 贪心:如果栈顶元素等于popped序列中下一个值,则应立刻将该值pop出来复杂度: ●时间:O(N),入栈一次出栈一次 ●空间:O(N),辅助栈代码:class Solution {public: bool validateStackSequences(vector<int>& pushed, vector<int>& popped) { if(pushed.size() != popped.size(.原创 2021-02-21 22:13:09 · 74 阅读 · 0 评论 -
剑指offer Leetcode 30. 包含min函数的栈
解法1:辅助栈思想: push和pop操作本来就是O(1),所以只需要一个辅助栈来实现O(1)的min就好了。 辅助栈B的栈顶就是A中元素的最小值代码:class MinStack {private: stack<int>A; stack<int>B;public: /** initialize your data structure here. */ MinStack() { } vo.原创 2021-02-21 22:12:35 · 57 阅读 · 0 评论 -
剑指offer Leetcode 66. 构建乘积数组
解法:左 * 右思想: 不能用除法,那就将左边和右边分开,最终相乘复杂度:●时间:O(N)●空间:O(1)代码注意点: left每次*的是a[i - 1] right每次*的是a[j + 1]不能漏掉这两个1代码:(两次循环,可改进)class Solution {public: vector<int> constructArr(vector<int>& a) { //多次用到a.size(),所以存起来 .原创 2021-02-21 22:11:42 · 69 阅读 · 0 评论 -
剑指offer Leetcode 61. 扑克牌中的顺子
注意 牢记构成顺子的两个条件●无重复的数字(除0)●最大值 - 最小值 < 5(除0)解法:set + 遍历思想: 同时满足以下两个条件,这5张牌可构成顺子。无重复的牌 (大小王除外)最大牌 - 最小牌 < 5 (大小王除外)复杂度:●时间:O(1),五个元素●空间:O(1),set中五个元素代码:class Solution {public: bool isStraight(vector<int>& nums) { .原创 2021-02-21 22:10:53 · 118 阅读 · 1 评论 -
剑指offer Leetcode 51. 数组中的逆序对
解法1:暴力法(超时)思想: 每次固定一个节点,遍历其后的节点复杂度: ●时间:O(N^2) ●空间:O(1)代码:class Solution {public: int reversePairs(vector<int>& nums) { if(nums.size() <= 1) return 0; int res = 0; for(int i = 0; i < nums..原创 2021-02-21 22:10:12 · 94 阅读 · 1 评论 -
剑指offer Leetcode 39.数组中出现次数超过一半的数字
解法1:哈希表思想: 用哈希表记录出现的个数,有超过一半的就返回复杂度: 时间:O(n) 空间:O(n)代码:class Solution {public: int majorityElement(vector<int>& nums) { unordered_map<int, int>nums_map; for(int i : nums){ ++nums_map[i]; .原创 2021-02-21 22:09:17 · 61 阅读 · 0 评论 -
剑指offer Leetcode 29.顺时针打印矩阵
解法:思想:复杂度: ●时间:O(mn) ●空间:O(1)代码:class Solution {public: vector<int> spiralOrder(vector<vector<int>>& matrix) { if(matrix.empty() || matrix[0].empty()) return {}; int m = matrix.size(), n = ma.原创 2021-02-21 22:08:42 · 76 阅读 · 0 评论 -
剑指offer Leetcode 21.调整数组顺序使奇数位于偶数前面
解法:双指针思想: 从两边开始遍历,两边都在不符合的地方停顿,然后两边交换,直到遍历完成。代码:class Solution {public: vector<int> exchange(vector<int>& nums) { int i = 0, j = nums.size() - 1; while(i < j){ //注意,要时刻判断i < j while((n.原创 2021-02-21 22:07:56 · 76 阅读 · 0 评论 -
剑指offer Leetcode 4.二维数组中的查找
class Solution {public: bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) { //记住要判断输入的合法性 if(matrix.size() == 0 || matrix[0].size() == 0) return false; int n = matrix.size(), m = ma..原创 2021-02-21 22:06:43 · 67 阅读 · 0 评论 -
剑指offer Leetcode 3.数组中重复的数字 + 287.寻找重复数
注意:要问面试官时间/空间以及是否能修改原数组的需求。解法1:排序然后找出重复的数字,时间复杂度O(nlogn) 不需要额外空间解法2:哈希表,unordered_set。解法3:数组实现哈希表,因为规定了所有数字都在0~n-1范围内。时间复杂度O(n),空间复杂度O(n)class Solution {public: int findRepeatNumber(vector<int>& nums) { vector<int>map(nums.原创 2021-02-21 22:05:03 · 113 阅读 · 0 评论 -
剑指offer Leetcode 68-II.二叉树的最近公共祖先
解法:递归思想:●终止条件: 1.root为NULL,返回NULL 2.p或q为root,直接返回root●递推: 1.对左子进行递归,返回值记为left 2.对右子进行递归,返回值记为right●返回值:根据left和right为空和不为空,展开为四种情况 1.同时为空,说明左右子树都不包含p和q,返回NULL 2.同时不为空,说明一个在左,一个在右,返回root 3.left为空,right不为空,说明p,q都不在left中,返回right 4..原创 2021-02-18 22:05:34 · 69 阅读 · 0 评论 -
剑指offer Leetcode 55-II 平衡二叉树
解法1:递归(大量重复计算,时间复杂度高)思想: 一个节点平衡 = 左子平衡 && 右子平衡 && 左子右子深度相差不超过1所以需要定义求深度的函数缺点: 计算一个节点深度时,也计算了子节点的深度,所以计算第二层时也计算了第三层的深度,但是后面还是要计算第三层的深度,所以有很多重复计算复杂度: 时间:要遍历O(logN)层,每一层需要O(N)时间,所以O(NlogN)代码:class Solution {public: // 一个节点.原创 2021-02-18 22:04:42 · 77 阅读 · 0 评论