菜菜做题
Am最温柔
每天都有觉得自己太菜的焦虑,解决方法也很简单,好好学习就行了,今天也要加油鸭~
展开
-
字符串转换整数 (atoi)
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。函数 myAtoi(string s) 的算法如下:读入字符串并丢弃无用的前导空格检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。将前面步骤读入的这些数字转换为整数(即,“123” -原创 2022-05-13 17:41:23 · 281 阅读 · 0 评论 -
寻找两个正序数组的中位数
可以理解为寻找第k个数字。使用二分的思想,将两个数组的第k/2个数字进行比较,一次排除k/2个数字。如果数组长度小于k/2需要取数组剩余长度,如果一个数组已经处理到最后了,那么直接返回另一个数组的给定位置的值即可。getKth中的k可以理解为找第k个数字(从1开始,找第1个,第2个,…,第k个数字)。class Solution {public: double findMedianSortedArrays(vector<int>& nums1, vector<in原创 2022-05-02 21:13:58 · 331 阅读 · 0 评论 -
剑指 Offer 11. 旋转数组的最小数字
这道题虽然是一个简单题,但是我觉得还是比较有难度的。需要使用二分查找降低时间复杂度。难点1: 使用二分查找时,不断地将mid值与right值比较,而不是与left值比较才行。具体原因是:对于一个旋转数组来说例如[3,4,5,1,2]。当mid值大于left时,需要收缩左边界。而当mid值小于left时,需要收缩左边界。而对于[1,2,3,4,5]这种没有旋转的数组来说,当mid值大于left时(必然发生),应该收缩右边界。此时出现了矛盾,也即,当mid值大于left时,无法判断应该收缩左边界还是原创 2022-05-01 13:30:36 · 171 阅读 · 0 评论 -
二叉树的后序遍历
需要注意的点:后序遍历与中序遍历的区别是,当访问某个节点是,可以确定其左孩子已经被访问过了,但是右孩子是否被访问过了还无法确定,因此需要使用一个prev变量,记录一下前一个被访问过的节点,如果右孩子是这个已经被访问过的节点,或者右孩子为空时,此时才能访问当前节点。(访问过该节点的含义是,将该节点放入了res数组,对于后序遍历,其必要条件是,该节点的左孩子和右孩子都被访问过了)/** * Definition for a binary tree node. * struct TreeNode { *原创 2022-04-17 19:23:17 · 1042 阅读 · 0 评论 -
N叉树的前序遍历和后序遍历
N叉树的前序遍历和后序遍历代码非常相似,只需要修改将val放入res数组的位置即可。需要注意的两点:多叉树遍历需要使用一个map来记录,已经遍历到了第几个孩子节点。1.这个map记录的是,哪个节点已经访问到第几个子节点了。unordered_map也可以用地址作为key。2.多叉树遍历的过程中,pop操作是在当前节点的所有子节点访问结束之后才可以pop。class Solution {public: vector<int> postorder(Node* root) {原创 2022-04-17 19:16:56 · 1082 阅读 · 0 评论 -
剑指 Offer 14- I. 剪绳子
给你一根长度为 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。注意:题目要求应该是必须要剪一刀,这样如果绳长度为2时,结果为1;长度为3时,结果为2解题思路:dp:递推公式为 f(n) = max(f(n-i)*f(i)) 其中i的取值为[1,n/2原创 2021-06-11 00:01:23 · 84 阅读 · 0 评论 -
剑指 Offer 29. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。解题思路:按层打印,每一层分为上,右,下,左四个部分组成。先计算矩阵的层数,矩阵较短的一边除以2向上取整可得。上右下左四个方向打印的思路很容易想,但是实际遇到一些没想到的点。1.横纵坐标弄反了= = left right实际对应的是矩阵的列。2.对于下和左两个方向,i应该递减不是递增 = =3.矩阵下标不能小于0这里要加判断4.在left==right或者top==botom时,可以不用进行下和左的打印,否则,按照我写的代码,会多原创 2021-06-06 16:51:37 · 132 阅读 · 0 评论 -
剑指 Offer 58 - I. 翻转单词顺序
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。解题思路:使用一个栈,从后向前将字符串每个字符入栈,如果遇到空格(或到了整个字符串的开始位置),则将栈中元素放到一个字符串中,并追加到结果中。class Solution {public: string reverseWords(string s) { int n = s.size原创 2021-06-02 00:12:04 · 211 阅读 · 0 评论 -
剑指 Offer 44. 数字序列中某一位的数字
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。我太菜了= =,写这么个小破函数 ,费死劲了。代码写的也不好,先这样哈思路:找规律1-9 9个数 占9位10-99 90个数 占902位100-999 900个数 占903位使用此规律寻找数位上的数字,分三个步骤:1.确定该数位的数字(下面代码中变量:target)是几位数2.确定该数位原创 2021-06-02 00:08:54 · 82 阅读 · 0 评论 -
剑指 Offer 41. 数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。例如,[2,3,4] 的中位数是 3[2,3] 的中位数是 (2 + 3) / 2 = 2.5设计一个支持以下两种操作的数据结构:void addNum(int num) - 从数据流中添加一个整数到数据结构中。double findMedian() - 返回目前所有元素的中位数。解题思路两个堆使用两个堆,原创 2021-04-22 14:57:50 · 229 阅读 · 0 评论 -
剑指 Offer 60. n个骰子的点数
题目把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。概率论知识复习样本点随机试验可能出现的结果,这些结果称为样本点。样本空间样本点全体构成样本空间。事件定义为样本点的某个集合,称某事件发生,当且仅当它所包含的某一个样本点出现。(例如投掷2个骰子,其点数和为3即为一个事件,包含两个样本点:(1,2)(2,1),当然,样本点本身也是一个原创 2021-04-19 23:08:40 · 149 阅读 · 0 评论 -
剑指 Offer 36. 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。为了让您更好地理解问题,以下面的二叉搜索树为例:我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱原创 2021-04-19 11:03:20 · 77 阅读 · 0 评论 -
剑指 Offer 48. 最长不含重复字符的子字符串
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。解题思路:1.使用《剑指offer》上的解题思路:2.使用动态规划+哈希表方法。3.更新规则:f(i)代表以第i个字符为结尾字符的最长不重复字符串长度,此为dp数组(但是代码中没有使用O(n)的空间建立一个数组,由于只需要获得最大长度,使用打擂台的方式获取最大值即可。)对于第i个字符,如果该字符未在哈希表中出现过,那么f(i)=f(i-1)+1;如果它在哈希表中出现过,那么分为两种情况:(1)如果它最后一次出现的位置距原创 2021-04-18 20:58:17 · 158 阅读 · 0 评论 -
剑指 Offer 61. 扑克牌中的顺子
犯了一个错误:我先把第i个数字放到集合中,然后去集合中找元素,这样的结果是一定可以找到的,所以应该先找后放。解题思路:1.对数组中数字进行排序2.利用集合保证其不能有重复数字,如果有则直接返回失败,但是0可以重复。3.如果2步骤没有返回,说明没有重复数字,那么此时最大与最小数字差小于5即可,此时一定可以连成顺子。class Solution {public: bool isStraight(vector<int>& nums) { //0.排序原创 2021-04-11 22:26:43 · 81 阅读 · 0 评论 -
22. 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。有效的:["((()))","(()())","(())()","()(())","()()()"]无效的:[")()()(",")())((","))(()(","))()((",")))((("]解题思路:backtracking(n,n):将具有n个左括号和n个有括号的有效的全排列字符串加入到Res中递归的退出条件:该放的都放完了递归将问题规模缩小,这种就是放一个左括号之后,我们放左括号的任务就原创 2021-03-20 16:08:01 · 68 阅读 · 0 评论 -
46. 全排列
解题思路:回溯backtracking函数的作用:将nums数组在使用情况为used数组时,即排除used数组中已经使用过的元素之后,剩下的元素进行全排列,并将这个全排列加入到path中,如果达到数量,则将其加入结果队列中。class Solution { vector<int> path; vector<vector<int>> res;public: vector<vector<int>> permute(vec原创 2021-03-20 15:13:05 · 77 阅读 · 0 评论 -
141. 环形链表
错误:循环退出点写错了:应该选择每次循环都改变的变量进行判断。循环中判断的条件位置写的不对,应该先让两个指针走两步,然后在判断/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */class Solution {public: bo原创 2021-03-17 22:46:49 · 60 阅读 · 0 评论 -
剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数没有返回值解题思路:剑指offer上的三次翻转方式class Solution {public: string reverseLeftWords(stri原创 2021-03-16 23:22:04 · 69 阅读 · 0 评论 -
剑指 Offer 50. 第一个只出现一次的字符
题目:在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。这个是我自己第二次做写的代码:其中Find的使用也不是自己想起来的,和使用c++11方式的遍历相比,这种方式的遍历代码上感觉好麻烦。1.最开始使用的是map,后来发现没有必要使用有序的结构。2.find 函数使用不够熟练3.循环的方式可以改进解题思路:使用哈希表,如果第一次出现在哈希表中,则将其值置为true,如果不是第一次出现,那么将其值置为false。题目中要求第一个出现,则可以对字符串中的原创 2021-03-16 23:07:18 · 102 阅读 · 0 评论 -
101. 对称二叉树
判断一棵树是不是对称二叉树解题思路:compare函数的作用是,判断两棵树是否对称。如果一个树的左右子树对称,那么这棵树是一个对称二叉树。判断方式:如果树1的左子树和树2的右子树对称,同时树1的右子树和树2的左子树对称,那么树1和树2对称/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; *原创 2021-03-12 23:32:42 · 68 阅读 · 0 评论 -
剑指 Offer 27. 二叉树的镜像
解题思路:递归的退出条件:当当前节点为空时退出单层的思路:1.将root的左右子树交换位置2.将左子树的左右子树交换位置3.将右子树的左右子树交换位置/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), righ原创 2021-03-12 23:02:15 · 58 阅读 · 0 评论 -
剑指 Offer 53 - I. 在排序数组中查找数字 I
统计一个数字在排序数组中出现的次数。解题思路:利用二分查找:(感觉自己能写出二分查找了,嘻嘻)错误点;if(mid+1<n&&nums[mid+1]!=target||mid==n-1){这个或条件没写出来,两种情况可以直接返回:1.如果当前元素的下一个元素的值不等于Target,那么说明当前元素为后边界2.如果当前元素为最后一个元素,那么当前元素为后边界。class Solution {public: int search(vector<int>原创 2021-03-11 23:58:08 · 63 阅读 · 0 评论 -
剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。解题思路:借助快排partition函数 (这次partiton函数没有写错,嘻嘻)错误点:没有写这一行,如果不写当nk时会溢出,if(nk) return arr;这个地方竟然忘记写pos了,pos = partition(arr,beg,end);class Solution {public: vector<int> getLeas原创 2021-03-11 23:20:39 · 69 阅读 · 0 评论 -
169. 多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。这种方式超时了,但是使用partition函数的思路可以借鉴:由于多数元素一定出现在数组的中间位置,那么使用快排的partition函数能够帮助定位。解题思路:partition函数的作用是:int partition(vector<int>& nums,int beg,int end)对于给定的nums,开始和结原创 2021-03-10 23:23:01 · 72 阅读 · 0 评论 -
122. 买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。解题思路:动态规划,dp[i][0]代表第i天结束后,不持有股票时能够拥有的最大现金数量。dp[i][1]代表第i天结束后,持有股票时能够拥有的最大现金数量。在第0天开始时,不持有股票,现金数量为0.对于dp[i][0]的递推公式:如果第i天结束后不持有股票,有两种可能:(1)第原创 2021-03-06 11:17:52 · 91 阅读 · 0 评论 -
121. 买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。解题思路:dp数组dp[i]的意义是在第i天能够获得的最大收益,递推公式: dp[i] = max(dp[i-1],prices[i]-min);维护一个min,截止到第i天所看到的最小值就可以啦 还原创 2021-03-05 22:25:09 · 71 阅读 · 0 评论 -
494. 目标和
给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。返回可以使最终数组和为目标数 S 的所有添加符号的方法数。解题思路;dfs(如果不看答案我肯定想不到使用dfs)dfs作用://nums数组,从位置pos开始(当前位置还没有计入到当前和中,也即如果pos=nums.size()-1那么这个dfs本层仍然不能返回,需要将当前位置值加入到当前和中),当前和为curSum,目标和为t原创 2021-03-01 11:22:55 · 75 阅读 · 0 评论 -
20. 有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。解题思路:借用栈遍历这个字符串,如果遇到左括号,则将对应的右括号入栈,如果遇到右括号,则检查是否栈空,或者栈顶元素与其不同,如果不同或栈空,则返回错误。否则,pop弹出。循环结束后,如果栈为空,则是有效的括号class Solution {public: bool isValid(string s)原创 2021-02-26 18:02:24 · 66 阅读 · 0 评论 -
219. 存在重复元素 II
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。解题思路:利用哈希表,一次遍历,时间复杂度O(n)1.对每一个数组中的元素,先检查是否哈希表中有这个元素,如果没有,将其放入哈希表中,键位nums[i]值为i;如果没有,则检查其距离是否小于k,如果小于,返回true,如果不小于,那么使用新的num[i]下标i替换原有下标。class Solution {public: b原创 2021-02-26 17:49:11 · 70 阅读 · 0 评论 -
69. x 的平方根
实现 int sqrt(int x) 函数。计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。思路:使用二分查找class Solution {public: int mySqrt(int x) { int left=0,right=x; while(left<=right){ int mid = left + (right-left)/2; if((long long)mid*mid<原创 2021-02-26 17:26:03 · 77 阅读 · 0 评论 -
剑指 Offer 10- I. 斐波那契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))解题思路:简单动态规划,注意的点:定义dp数组时,需要将其大小设为n+2(设成n+1就报错:heap buffer overflow,我也不懂为什么)class Solution {public: int fib(int n) { vector<int> dp(n+2,0); dp[0] = 0; dp[1] = 1; for(i原创 2021-02-26 17:24:34 · 64 阅读 · 0 评论 -
力扣349. 两个数组的交集
给定两个数组,编写一个函数来计算它们的交集。解题思路欢迎大家关注,我会持续更新刷题题解,希望对大家有所帮助!此题考查的是哈希表知识内容里的unordered_set解法。此题用unordered_set的原因是:输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的,同时可以不考虑输出结果的顺序。此题不使用数组的原因是:哈希值比较少,特别分散,跨度非常大,使用数组会造成空间的极大浪费。详情如下代码:代码class Solution {public: vector<int原创 2021-02-24 23:33:19 · 174 阅读 · 0 评论 -
力扣 200. 岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。解题思路:DFS函数的作用:找到包含grid[i][j]格子的岛屿的全部格子,并将其全部置为’2’(已访问状态)。注意点:1.将访问过的网格设置为‘2’ 而不是 ‘0’,因为设置为0会导致无法区分是访问过的陆地还是海洋。2.可以将DFS类比于递归法遍历二叉树。(1)递归的退出条件:1)如原创 2021-02-19 22:47:56 · 90 阅读 · 1 评论 -
剑指 Offer 46. 把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。解题思路:动态规划,dp[i]元素的含义是,以str[i]为结尾的数字的翻译方法数量。举例12225,现将该数字存储在str中(string类型),dp[4](下标最大值)代表以str[4](值为5)结尾的数字的翻译方法数量。可以看到dp[4] = dp[3](将5单独翻译)+原创 2021-02-16 15:09:24 · 122 阅读 · 0 评论 -
剑指 Offer 35. 复杂链表的复制
剑指 Offer 35. 复杂链表的复制解题思路:利用哈希表,两次遍历,第一次遍历,将新的链表所有节点的内存申请出来,第二次遍历建立新链表的next指针和random指针。(哈希表可真好用)/*// Definition for a Node.class Node {public: int val; Node* next; Node* random; Node(int _val) { val = _val; next =原创 2021-02-16 13:29:46 · 59 阅读 · 0 评论 -
剑指 Offer 56 - II. 数组中数字出现的次数 II
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。解题思路:利用哈希表(我觉得思路非常简单舒适了),也可以利用位运算(第二刷再说吧哈哈)。class Solution {public: int singleNumber(vector<int>& nums) { map<int,int> mp; for(int i:nums){ mp[i]++;原创 2021-02-16 13:00:57 · 83 阅读 · 0 评论 -
剑指 Offer 65. 不用加减乘除做加法
剑指 Offer 65. 不用加减乘除做加法写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。解题思路:利用位运算:1.利用异或运算计算没有进位的和。2.利用与运算加左移一位计算进位。错误点:如果不写 carry = (unsigned int)(a&b)<<1;中的 (unsigned int)就会报错:runtime error: left shift of negative value -2147483648 (soluti原创 2021-02-15 14:11:43 · 194 阅读 · 1 评论 -
剑指 Offer 64. 求1+2+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。解题思路:利用构造函数,构造n个对象(一个有着n个对象的数组),那么这个加的动作就能执行n次。(利用构造函数实现循环)。代码:建立一个temp类,通过该类的构造函数实现加法的循环我的错误点:1.需要将temp类中的init() 和 ret()方法设置为static函数。这样可以在不指定对象的时候调用类方法。2.需要在类外对num和sum变量进行初始化(我不太明原创 2021-02-15 13:47:50 · 119 阅读 · 0 评论 -
剑指 Offer 45. 把数组排成最小的数
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。解题思路:实际上是定义了一个新的比较大小的方式,对于两个数字m,n,如果其拼接成的数字mn<nm,则定义此时m<n,例如321和32,显然有32132<32321,因此,321小于32.按照这种方式进行排序的数组能够保证顺序连接之后的数字最小。错误点:开始时没有将cmp声明为Static函数,必须声明为static函数的原因是:对于sort函数这个全局函数来说,在调用cmp时,并没有一个指原创 2021-02-14 14:18:08 · 88 阅读 · 0 评论 -
剑指 Offer 07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。解题思路:根据前序序列找到根节点的值(第一个),根据中序序列确定二叉树的左右子树,在根节点左边的是左子树的中序序列,根节点右边是右子树的中序序列。递归的重建左右子树。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNo原创 2021-02-14 12:38:02 · 88 阅读 · 0 评论