08 2020 档案
摘要:对于每个位置的两个数之间,都有四种选择:加、减、乘、不填符号(这样两个数就连在一起构成一个更大的数)。 我们可以构造一个代数结构,使得不管下一个位置的数是什么,这个数后面填什么符号,我们都能记录前面已经计算过的字符串的值。 这个代数结构是a + b × c。 a 是我们前面记录过的字符串表达式的值,
阅读全文
摘要:用dp[i]表示组成i的最少的完全平方数的个数。 如果有一个j, 1<=j且jj ⇐ i,如果j的平方是组成i的完全平方数的其中之一个完全平方数,则可以考虑用dp[i - j * j]来更新dp[i]。 即dp[i] = min(dp[i], dp[i - j * j] + 1); 表示组成i的最少
阅读全文
摘要:调用题目给的API,二分查找第一个错误的版本。 // The API isBadVersion is defined for you. // bool isBadVersion(int version); class Solution { public: int firstBadVersion(in
阅读全文
摘要:class Solution { public: int hIndex(vector<int>& citations) { int n = citations.size(); int res = 0; for(int i = n - 1; i >= 0; --i) { if(citations[i]
阅读全文
摘要:对所有citations排序,然后从大到小找第一个满足条件的那个citations就是H指数。 class Solution { public: int hIndex(vector<int>& citations) { int res = 0; int n = citations.size(); c
阅读全文
摘要:英文里每三位就有个逗号,所以我们单独写一个函数处理每三位数之间的表示,然后再根据当前处理的三位数的位数来决定后面是否要加上"thousand","million"啥的。 代码如下: class Solution { public: unordered_map<int, string> numInEn
阅读全文
摘要:0~n有n+1个数,可以根据等差数列求和公式快速算出总和。减去nums数组的n个数,就能在线性时间内算出缺少了哪个数。 class Solution { public: int missingNumber(vector<int>& nums) { int n = nums.size(); int e
阅读全文
摘要:因为丑数的因子只有2,3,5,所以我们可以用三指针指向当前最大的三个丑数,下一个丑数必然是当前最大的三个丑数×2、×3、×5得到的三个数中 最小的那一个。 得到新的丑数之后,做了乘法的那个指针就往前移动,这样三个指针时刻指向最大的三个丑数。 class Solution { public: int
阅读全文
摘要:如果一个数只包含这几个质因子,那就不断的除以这几个质因子,最后如果只剩下1,就是丑数。 class Solution { public: bool isUgly(int num) { while(num >= 5 && num % 5 == 0) { num /= 5; } while(num >=
阅读全文
摘要:我们知道两个相同的数异或之后就为0,所以对于nums数组中的所有数,异或之后的结果就是那两个只出现一次的数异或的值。 这个值必然不为0(因为这两个数是不同的),所以这个数的二进制表示里,从低位往高位必然有一位1,这一位是1,说明这两个数 在这一位的二进制表示不同(因为这个数是异或得到的),我们可以以
阅读全文
摘要:将二叉树先序遍历解码为一个序列字符串s,不同的数字之间用逗号分隔,如果遇到空节点,就只在s加上一个","。 如果不是空节点,就先加上当前节点的值,然后再加上逗号。 解码的时候,也是取两个逗号之间的值,如果逗号之间为空,则说明是空节点,否则new一个TreeNode出来,节点的值就是两个逗号之间的 子
阅读全文
摘要:用dp[i]记录以nums[i]结尾的最长上升子序列的长度。 遍历数组,对于一个数,从开头遍历到这个数的前一个数,如果存在一个(0 ⇐ j ⇐ i - 1),nums[j] < nums[i] 且 dp[j] > 1, 则可以考虑更新dp[i] → dp[i] = max(dp[i], dp[j]
阅读全文
摘要:先同时遍历两个数组,计算相同位置上相同的字母个数,记为cntA。 在遍历的同时,如果相同位置上两个字母不同,就在一个哈希表unordered_map<char, int>上记录不同的数字(在字符串secret)出现的次数。 然后遍历guess数组,用一个变量cntB记录出现在秘密数字中,但位置不一致
阅读全文
摘要:暴力做法是维护一个数组,每次插入一个元素就对数组进行排序,然后通过有序数组寻找中位数就很简单了。 但是因为每次插入一个元素都要对数组进行排序,调整的时间代价太大了,超时。 我们可以用两个优先级队列,一个小根堆,一个大根堆分别存储大于等于和小于当前中位数的所有数。 且小根堆的大小总是和大根堆的大小相等
阅读全文
摘要:找规律的题目,对于1, 2, 3块石头,由于我们可以一次拿走,所以必赢。 而如果是4块石头,不管我们拿多少块(1、2、3),最会剩下1~3块,使得对手可以一次拿走,所以必输。 我们管n=1,2,3叫必胜态,n=4叫必败态。 注意到,一个必败态的n加上1,2,3,又变成了必胜态。比如n=5,6,7的时
阅读全文
摘要:可以用两个哈希表分别记录pattern到str(即字母到单词)和str到pattern(即单词到字母)的映射。 然后检查两个哈希表中的记录,比如某个字母之前已经映射到某个单词,但存在和这个映射矛盾的映射(字母映射到别的单词), 或者是存在某个矛盾的从单词到字母的映射,就返回false。 否则,遍历完
阅读全文
摘要:可以直接额外写一个函数count计算周围每个格子周围八个位置中活细胞的数目,再根据当前位置是活细胞还是死细胞以及周围 活细胞的数目更新当前位置board的值。 class Solution { public: vector<vector<int>> g; int rows, cols; int dx
阅读全文
摘要:因为所有数字都在1n之间,所以我们可以枚举1n,然后再遍历nums数组看一下是不是有数字出现次数超过1次。 这样时间复杂度是O(n^2),还可以优化。 考虑这样一种情况,如果每个数字x(1<=x<=n)在数组里出现次数超过1次,则我们遍历数组的时候计算所有小于等于x的 数的个数cnt,cnt必然大于
阅读全文
摘要:这题给的类原型里PeekingIterator类公有继承自类Iterator,所以我们可以调用基类的next()和hasNext()方法。 虽然在class Iterator里只对next()和hasNext()方法做了声明,但是实际上类外肯定对这两个方法做了实现,所以我们 是可以直接调用Itera
阅读全文
摘要:双指针,用两个指针zero和nonZero分别找到一个为0和一个不为0的数,且如果不为0的数在为0的数后面,则交换这两个数。 如果在0的前面,则不用交换,zero指针不动,nonZero从zero指针的下一个位置开始寻找一个不为0的数,与zero指针交换。 重复这个过程,直到两个指针其中之一越界。
阅读全文
摘要:第一题 5479. 千位分隔数 把数字转换成字符串并翻转,然后每三位加一个".",之后再翻转字符串,就是最终的答案了。 class Solution { public: string thousandSeparator(int n) { string N = to_string(n); revers
阅读全文
摘要:如果不考虑进阶的条件,可以直接循环或者递归,把一位上的所有数字加起来然后对10取余。 class Solution { public: int addDigits(int num) { int sum = 0; while(num >= 10) { sum = 0; while(num != 0)
阅读全文
摘要:一顿dfs就行了,dfs参数里传一个string变量path记录从根节点到当前节点的路径的字符串。 然后dfs里面加一些判断,如果是空就return,如果左右子树都为空就现在结果数组res里记录当前的路径path,然后return。 然后在路径path上加下"->",如果左子树不空就dfs左子树,如
阅读全文
摘要:对字符串中所有字母做哈希,计算字母的出现频率,哈希表unordered_map<char, int> HashS记录字符串s中每个字母的 出现频率,unordered_map<char, int> HashT记录字符串t中每个字母的出现频率,如果两个哈希表相等,说明t是s的有效 字母异位词,否则不是
阅读全文
摘要:可以枚举所有的运算符的位置,然后递归算出该运算符左右的表达式所有可能的取值,然后对所有可能的取值进行计算。 首先,我们需要把原字符串input中的所有数字和运算符都放到一个vector里,因为每个数字的长度不确定,所以放到 vector里方便我们进行计算。 然后写一个计算expr某段区间的所有表达式
阅读全文
摘要:给定二维矩阵,搜索是否存在目标值target,暴力做法可以两重循环遍历数组进行搜索,这样时间复杂度是O(rows * cols), 其中rows,cols为二维矩阵matrix的行数和列数。 我们可以用给定的性质进行优化,因为每行的元素从左到右升序排列,每列的元素从上到下升序排列。 所以我们可以从右
阅读全文
摘要:暴力做法:可以在遍历数组的时候,当i-k+1>=0(表示当前滑动窗口的大小达到了k),就遍历i-k+1 ~ i的所有元素,寻找最大值, 然后把最大值压入到结果数组res中,显然这种做法需要两重循环,时间复杂度为O(n*k)。 我们考虑一下优化,暴力做法在遍历数组的时候还需要在内层循环遍历来计算当前窗
阅读全文
摘要:要求出某个数除自身以外的数组的乘积,就要求出这个数前面所有数的乘积和这个数后面的所有数的乘积。 求出这个数前面或者后面所有数的乘积可以用前缀和或者后缀和对数组元素进行连续的乘积得到,但是由于这题限制了我们 只能开一个数组(最后的返回数组),所以前缀和用了数组记录之后,后缀和不能再用数组了。 不过没关
阅读全文
摘要:这题给出的节点是要删除的节点,而不是要删除的节点的前驱节点,所以,如果直接把这个节点删掉的话,单链表就断掉了, 没办法,所以不能动这个要删除的节点,不过我们可以动这个要删除的节点的下一个节点,但是下一个节点不是我们要删除的节点, 因为他的值我们需要保留,正好我们可以把我们现在指向的节点node的值修
阅读全文
摘要:对情况进行分类: (1)如果root为空,则返回NULL; (2)如果p和q其中之一为root,则这个节点就是最近公共祖先,返回root; 其他情况下,p和q有可能都在root的左子树、都在root的右子树、或者左右子树各一个; (3)递归计算lowestCommonAncestor(root →
阅读全文
摘要:二叉搜索树的性质:(1)root为空;(2)或者root左子树中所有元素都小于root->val,root右子树中所有元素都大于root->val, 且root的左右子树也是二叉搜索树。 所以要找两个节点的最近公共祖先,有三种情况: (1)p,q都在root的左子树中,则我们到root的左子树去寻找
阅读全文
摘要:第一题 1539. 第 k 个缺失的正整数 用一个数组missed记录从小到大、所有arr数组缺失的正整数可以把所有出现过的元素放入一个set里,然后从 1~2000开始枚举(因为arr长度和k的大小最大都是1000,所以答案一定小于2000),如果当前枚举到的这个数在 set中没有出现,说明arr
阅读全文
摘要:第一题 1544. 整理字符串 简单模拟,用一个字符串res记录结果,然后遍历原字符串,如果res为空或者当前字母与res的最后一个字母不是同一个字母的大小写形式, 就把当前字母加入到res字符串中,否则,删除res的最后一个字母。 class Solution { public: string m
阅读全文
摘要:第一题 5185. 存在连续三个奇数的数组 class Solution { public: bool threeConsecutiveOdds(vector<int>& arr) { int size = arr.size(); for(int i = 0; i + 2 < size; ++i)
阅读全文
摘要:套一个快速排序的模板,然后返回第k大的元素即可。 代码如下: class Solution { public: void quick_sort(vector<int> &nums, int l, int r) { //快速排序nums数组的[l ~ r]部分,细节分析看上面的链接 if(l >= r
阅读全文
摘要:这题是LeetCode198. 打家劫舍的进阶版,除了要求不能 打劫相邻的房子以外,还不能同时打劫第一个和最后一个房子。因为所有房子的排列是环形的,所以实际上第一个房子和 最后一个房子也是相邻的。 我们也用dp[i]表示打劫到第i个房子能获得的最大收益,要打劫到最后一个房子,就得不打劫第一个房子,所
阅读全文
摘要:这题是LeetCode79. 单词搜索的进阶版,第79题是在二维的char数组里搜索单个单词, 这题需要在二维char数组里搜索一组单词。 理论上只需要对遍历单词数组,逐个套用79的dfs方法即可,不过这题题目要求了需要用Trie树做优化。 所以,我们最开始可以把单词列表里的所有单词都插入到一个Tr
阅读全文
摘要:这题和LeetCode208. 实现 Trie (前缀树)一样,都是实现Trie树, 支持字符串的插入和查找,只不过这里的查找需要支持正则表达式,也就是可以用'.'代替任何单词,所以我们需要在查找部分做一些修改, 插入单词部分和208题一样。 对于查找单词,由于需要支持正则表达式,所以在查找单词wo
阅读全文
摘要:这题和LeetCode207. 课程表一样,都是拓扑排序的模板题,只不过207题只需判断是否存在拓扑序列, 这题要返回拓扑序列。 只需要在BFS时在一个结果数组中记录每个入队的元素即可,最后判断数组大小是否和课程总数量numCourses相同,相同就返回我们记录的所有元素的入队顺序的数组res, 不
阅读全文
摘要:LeetCode209. 长度最小的子数组 方法一 暴力枚举所有可能的子数组,也就是枚举子数组的所有开始下标和结束下标,计算子数组的和,如果子数组的和小于等于s,就更新最小长度。 class Solution { public: int minSubArrayLen(int s, vector<in
阅读全文
摘要:方法一 可以直接用一个数组trie存放所有插入的字符串,然后insert和startsWith操作只需要遍历trie数组,逐个判断即可。 代码: class Trie { public: vector<string> trie; /** Initialize your data structure
阅读全文
摘要:这题是拓扑排序的模板题。 先看一下拓扑排序的步骤: (1)遍历存放所有点之间的依赖关系的数组(这题是prerequisities数组),统计所有入度为0的节点,即没有任何先修课程的课程。 (2)有一个队列存放所有的点(入队顺序表示学习课程的顺序),将所有入度为0的节点入队。 然后进行BFS,不断取出
阅读全文
摘要:和整数二分不同,浮点数不存在由于(整数)取整导致的边界问题,每次二分区间严格减半, 因此比整数二分简单的多,每次更新边界时直接让r = mid或l = mid即可。 看一道题,acwing790.数的三次方根 浮点数二分除了更新区间和浮点数不同,还有就是二分终止条件,一般有两种写法,一种就是当前区间
阅读全文
摘要:整数二分有两个模板。 int bsearch_1(int l, int r) { while(l < r) { int mid = l + 1 >> 1; if(check(mid)) r = mid; else l = mid + 1; } return l; } 这种写法每次把区间压缩到**[l
阅读全文
摘要:原题链接:acwing787.归并排序 归并排序和快速排序类似,都是基于分治的,步骤如下: (1)确定待排序数组的分界点mid, 一般取mid为待排序数组的中位数 mid = l + r >> 1; (2)递归排序分界点的左右两侧区间,直到区间大小为1; (3)归并两个排好序的区间,把两个有序的数组
阅读全文
摘要:原题链接:acwing786.第k个数 一道快速排序的模板题,关于快速排序的原理和模板,可以参考[模板]快速排序 这里直接贴代码吧,和模板没什么区别,就输出排序后的第k个数而已。 #include<iostream> using namespace std; const int N = 1e6 +
阅读全文
摘要:原题链接:acwing785.快速排序 给定数组大小n和数组q[n],对数组进行排序。 快速排序的原理:基于分治 (1)确定分界点x:可以取x为q[l], q[l + r >> 1],q[r], 或者数组中间随机一个值(建议取q[l + r >> 1], 原因在后面说)。这里l和r是当前待排序数组的
阅读全文
摘要:状态机dp,可以参考LeetCode188. 买卖股票的最佳时机 IV。 我们有两个状态,当前交易的天数i和当前是否持有股票,我们用一个二维数组dp[n][2]表示各个状态所能获得的最大收益(其中n为prices数组的大小,表示交易的天数)。 比如dp[i][0]表示第i天(i从0开始),当前不持有
阅读全文
摘要:状态机dp,可以参考LeetCode188. 买卖股票的最佳时机 IV. 我们可以用一个数组dp[n][2]表示每一个状态下的最高收益(其中n是prices数组的大小,即总的天数)。 数组的第一维表示天数,第二维表示持有或不持有股票(1表示持有,0表示不持有)能获得的最大收益。 比如dp[i][0]
阅读全文
摘要:由于只能进行两次交易,且交易之间不能有交集,所以可以视为两段独立的交易时间,因此我们可以枚举所有的两次交易的“分界点”,比如我们以第二次交易的开始时间作为分界点,枚举从开头到当前这个点的所有时间内,如果只进行一次交易所能获得的最大收益(这就是第一笔交易所能获得的最大收益)。然后再从后往前枚举,更新从
阅读全文
摘要:题目说了可以无限次交易。又因为,对于一次从第i天买入,第j天卖出的交易方案,获得的利润等于prices[j] - prices[i],即只和这次交易的买入和卖出当天的价格有关。 所以对于一个跨越连续多天的交易可以分割为连续多个的跨越一天的交易。 所以我们只需要选择那些能够获利的“两天”进行交易(前一
阅读全文
摘要:由于只能交易一次,即买入卖出一次,所以我们考虑在某个价值较低的某天买入,在之后的某个价值较高的一天卖出,以获取最高的差价利润。 最简单的想法是枚举所有天数,然后枚举某天之后的所有天数,更新能够获取到的最高利润。 这样做需要两重循环,时间复杂度是O(n^2),超时。 我们可以边枚举天数边记录当前的最低
阅读全文
摘要:状态机dp,参考labuladong的题解 首先考虑状态表示,这题有三种状态,天数、当前进行的最大交易次数,以及当前是否持有股票。所以我们可以用dp[i][k][0或1]表示:当前是第i天(i从0开始),当前允许的最大交易次数为k(这里我们认为交易次数是买入股票的次数),0表示当前不持有股票,1表示
阅读全文
摘要:题意是寻找一个无序数组排序之后的相邻元素的最大差值。直观的思路是对数组进行排序,然后再在排序后的数组里寻找相邻元素的最大差值。 由于题目要求时间复杂度为O(n),所以我们不能用快速排序,而是用时间复杂度为O(n),空间开销较大的桶排序。 关于桶排序,可以参考这篇博客。 基本思想就是,我们先遍历一遍数
阅读全文
摘要:要判断是否会出现无限循环小数,就需要找循环节。 如果出现了循环节,会出现这样一种情况:被除数除以除数的商,在之前已经出现过了,比如2 / 3,2比3小,借位,20 / 3 = 6 ... 2, 然后商又是6,6在之前出现过了,所以我们知道循环节就是6。 最终结果就是0.(6)。 要记录之前已经出现过
阅读全文
摘要:根据题意,用'.'划分出两个版本的每个子版本号,从左到右逐个比较即可,如果某个版本的子版本号个数比另一个多,则子版本较少的那个版本用0表示子版本,这样就可以一直比较两个版本的所有子版本了。 划分子版本可以用双指针,划分出的子版本存到一个数组中,都划分好后就得到两个分别存放两个版本的子版本的数组,然后
阅读全文
摘要:可以利用栈的性质,遍历链表,把节点存入栈中,然后一个一个弹栈,连接成新链表。 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : v
阅读全文
摘要:既然同一个字符如果要替换,就都得替换成相同的字符,我们可以开哈希表记录某个字符映射成了哪个别的字符,但是由于两个字符不能映射到相同的字符上,如果a映射成o,r也映射成o,那么bar就可以替换成foo了,这是不符合题意的。 我们注意到,如果我们对foo也建立一个哈希表,那么o只能映射成一个字符,foo
阅读全文
摘要:暴力计算所有小于n的数中的素数个数。 class Solution { public: bool isPrime(int n) { if(n == 2) { return true; } for(int i = 2; i * i <= n; ++i) { if(n % i == 0) { retur
阅读全文
摘要:链表的“删除”,往往采用的是跳过的方式,即如果p → next是我们要“删除”的节点,我们只要把p的next指针指向p → next → next就可以了,也就是让链表跳过p → next,让这个节点“社会性死亡”。 根据这个思路,这一题里我们只需要遍历链表,判断节点值是否与我们要删除的相等,如果相
阅读全文
摘要:按照题目说的规则,不是快乐数的数,会陷入无限循环,永远得不到1,比如18,在第4次迭代的时候计算出来的n是58,在第12次迭代之后n的值还是58,所以就陷入了无限循环之中,所以18不是快乐数。 因此,我们可以用一个set,对于每一次迭代就算出来的n,都先去判断set中是否已经存在这个值了,如果已经存
阅读全文
摘要:暴力做法是,枚举从m~n的所有数,因为题目说了数据最大为2147483647,所以可以枚举0~30位,对所有数字的每一位做与运算。 数据比较大的时候这样做会超时(时间复杂度是O(n))。 参考官方题解,有一个简单得多的做法。 观察发现,要对所有数做按位与,只要有一个数的某一位为0,则最后按位与的结果
阅读全文
摘要:非常经典的搜索问题。遍历数组,从每一个1开始深度优先搜索当前位置联通的位置是否都是1(也就是与它联通的陆地),用一个额外的布尔数组visited记录每一个位置的元素是否已经访问过,每个遍历过的位置visited都标记为true。 代码如下: class Solution { public: vect
阅读全文
摘要:二叉树层次遍历,用一个数组记录每一层的最右边的元素。 class Solution { public: vector<int> rightSideView(TreeNode* root) { if(root == NULL) { return {}; } vector<int> res; queue
阅读全文
摘要:用dp[i]表示打劫到第i个房子(i从0开始)时能获取到的最高金额,显然对于第i个房子,我们有打劫和不打劫两种方案。 如果不打劫第i个房子,那么到第i个房子能获取的最高金额和到第i - 1个房子能获取到的最高金额是一样的(因为到了第i个房子这里没有收入嘛)。因此我们有dp[i] = dp[i - 1
阅读全文
摘要:循环,逐位判断每一位是不是1。 class Solution { public: int hammingWeight(uint32_t n) { int res = 0; for(int i = 0; i < 32; ++i) { res += (n >> i & 1) == 1 ? 1 : 0;
阅读全文
摘要:颠倒一个32位无符号整数的二进制位,因为它只有32位,所以我们可以用一个循环,从最低位开始获取它的当前位的数字,然后循环32次把数字加到一个新的32位无符号整数上,然后返回这个32位无符号整数就ok。 对于数字n,要获取最低位的数字就是 n & 1,也可以理解为n >> 0 & 1,意思就是n的二进
阅读全文
摘要:要右移k次,且只能用O(1)的空间,最简单的办法是循环k次,每次用一个变量temp记录最后一个位置的值,然后让最后一个下标(下标从0开始)到下标1的值都为前一个元素的值,再让下标0的值为temp。 这样进行k次之后,就完成了循环右移k次。 不过这样会超时,一个较简单的做法是,对于右移到数组前边的k个
阅读全文
摘要:动态规划,用dp[i][j]表示第i行第j列的格子到终点所需的最小初始值,这题如果从左上往右下递推,就需要同时记录从起点到当前位置的路径和以及从起点到当前位置所需要的最小初始值,比较麻烦。 因此我们可以从右下往左上递推,这样递推到每个格子只需要维护当前位置到起点(这里的起点是右下角了)的最小初始值,
阅读全文
摘要:几千位的字符串,肯定不能转成数字再加了(也转不了),不过还好只要做加法,可以对每一位进行加法,注意进位即可。 可以把两个字符串右对齐,然后对每一位进行加法,每一位计算出来的数字加到一个结果字符串里,这样计算完成后(遍历完num1和num2以及进位为0了), 就把字符串反转一遍,就得到了两个字符串相加
阅读全文
摘要:因为字符串可以按照字典序比较大小,所以可以自己写一个排序规则cmp,然后对数组中的所有整数转换成字符串之后再按照自己定义的规则排序。 排序之后,再将所有字符串连接起来,就是它们能够组成的最大整数。 注意特殊情况的判断,如果数组全是0,我们不想要输出"00000...00000"这种情况,只要输出一个
阅读全文
摘要:这题题目描述的有点不清楚,题意是给一个字符串,如果有某个子串(长度为10)重复出现了,就记录到一个数组里,最后返回的数组就是重复出现的子串组成的数组。 因为子串长度固定为10,所以遍历一遍就行,每个子串都记录到一个set里,这个set就是判断子串是否重复出现了,如果重复出现了,就记录到数组里。 但是
阅读全文
摘要:要实现二叉搜索树的迭代器,判断当前元素是否有下一个元素和知道下一个元素是多少? 好办,二叉搜索树的中序遍历序列不是升序的嘛,那我们就可以对二叉搜索树中序遍历一遍记录到一个全局变量数组里面,然后要判断是否有下一个元素和下一个元素是多少就很简单了。 代码如下: /** * Definition for
阅读全文
摘要:参考这个链接 直接计算阶乘,再求0的个数肯定会溢出,因为阶乘增长的很快。 所以需要观察一下规律,阶乘里出现0,肯定是能被10整除,而10只能由2*5组成,所以问题就转换为阶乘里有几对2和5. 由于2每两个数就出现一次,5要每5个数出现一次,所以阶乘里2的数量肯定比5多,所以问题又转换为寻找阶乘里5的
阅读全文
摘要:把每一位的字母转换成1~26的数字,再乘上pow(26, x),x是当前字符的位置到字符串末尾的距离,比如最后一个字母,就乘上26的0次方,也就是1. 倒数第二个字母,就乘上26的1次方,依次类推。 class Solution { public: int titleToNumber(string
阅读全文
摘要:遍历一遍数组,对所有元素的出现次数做哈希。 class Solution { public: int majorityElement(vector<int>& nums) { unordered_map<int, int> hash; int size = nums.size(); for(int
阅读全文
摘要:逆序来求字符串,每次把当前数字n对26取余,也就是当前这一位的字母,加到字符串里。 然后数字n整除26,再继续判断是否还能添加字符。 class Solution { public: string convertToTitle(int n) { string res; while(n != 0) {
阅读全文
摘要:既然题目都说了数组是升序的,那就双指针分别指向数组开头末尾,然后判断两个指针指向的数是否和target相等,如果和小于target,那么左指针右移,这样就可以让和增加了,如果和大于target,那么让右指针左移,这样就可以让和减小了,一直这样操作直到和等于target或者左右指针相遇。 代码如下:
阅读全文