leetcode
baixiaofei567
如果十年前没种树,那最好的时间是现在
展开
-
203. 移除链表元素
看似不难其实麻烦,设置一个虚拟头结点是关键。记得将虚拟节点和然后就是双指针,一个前一个后,分情况讨论。法一:设置虚拟节点后将其和head相连,因为我们不会每一次都将pre->next指向cur。如果是val,就让pre->next=cur->next,cur往后,pre别往后,因为不保证下一个cur就是正常的,可能下一个还是val,所以pre不能这么快更新。如果不是val,就把pre更新为cur,cur继续更新。/** * Definition for singly-linked.原创 2021-06-05 23:56:30 · 159 阅读 · 1 评论 -
525. 连续数组
前缀和周不用说了!还以为是dp嘞,看来连续子数组不仅要考虑dp还要考虑prefixsum我们把0看成-1,那么就变成了求一段和为0的最长解,所以我们用前缀和+哈希来做。前缀和是防止重复求和,哈希是为了快速查找相同是否有相同前缀和的情况,如果有,中间差的那一段一定是0!每一轮循环先更新前两位的,不能更新前一位的哦,不然要是和sum[i]相同,那么这一段连续子数组和可能是只有1个的,虽然不可能发生,但是还是要注意。直接判断前两位是否已存在,如果不存在就更新一下前两位的前缀和,因为要保证连续子数组长度&g.原创 2021-06-03 23:53:36 · 125 阅读 · 0 评论 -
523. 连续的子数组和
sum 是前 i+1 项和,每次加入集合的是前 i 项和的模。 当两个前缀和关于模 k 同余时,它们的差值就是满足条件的子数组和因为这两个前缀和%k的值一样,所以它们之间的差值一定是k的整数倍!为什么我们在每一轮加入的是sum-nums[i]对k的余数呢?因为这样在下一轮对sum+nums[i]进行判断的时候,差的就是两个,满足最小数量>=2的标准class Solution {public: bool checkSubarraySum(vector<int>& n.原创 2021-06-03 00:17:12 · 100 阅读 · 0 评论 -
1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
题解都在注释里,总的来说这是一道前缀和的题,在一个数组从i-j被重复计算的时候就要考虑用空间换时间,也就是前缀和。class Solution {public: vector<bool> canEat(vector<int>& candiesCount, vector<vector<int>>& queries) { //queries里每一个一维都是从第0天开始判断的,但是要把queries[i][0]前的糖果..原创 2021-06-02 00:25:08 · 88 阅读 · 0 评论 -
477. 汉明距离总和
一开始暴力了,想想就不行,立方级别的时间复杂度肯定不行的。不用两两异或,通过统计这个数组中每一位的1的个数和0的个数即可。因为是有范围不大于10^9也就是2 ^30,所以我们只要遍历0到30位就行,用每一位上的1的个数和0的个数相乘,就是这一位上能提供的所有汉明距离的和。1就是(val>>i)&1,0的个数就是n-c。为什么是0和1的相乘,就相当于做一个组合运算,用这一位是1的数字和另一个这一位是0的数字异或才能提供11的汉明距离,所以只要0的个数1的个数就是这一位所能提供的汉明距.原创 2021-05-29 00:02:50 · 100 阅读 · 0 评论 -
1190. 反转每对括号间的子串
一开始看到这题就感觉用递归or栈做,递归版本可能太久没写了,是不对的,还是向栈妥协了。栈中记录的是左括号的下标,当你碰到右括号的时候,将栈顶的左括号和其匹配并出栈,将这两个下标之间的字符串全部翻转,不包括(),包括也没事。最后再遍历tmp之后将其取出()就行了class Solution {public: string reverseParentheses(string s) { //递归翻转,写个函数,碰到(就进入,碰到)就退出 //将前面翻转好的,加上后..原创 2021-05-26 23:41:55 · 185 阅读 · 0 评论 -
692. 前K个高频单词
两种方法,先用哈希表记录词频,法一:来一个pair数组,先根据次数排序,再根据字母顺序排序。法二:维护一个大小为k的小顶堆,用优先队列即可class Solution {public: static bool cmp(pair<string,int> p1, pair<string,int> p2){ //true就不交换 //先根据次数,再根据字母顺序 if(p1.second != p2.second) return .原创 2021-05-21 00:38:43 · 102 阅读 · 0 评论 -
1723. 完成所有工作的最短时间
一眼就感觉是dfs爆搜,肯定超时,正解应该是递归回溯+二分+剪枝(做不来hhh)超时版本:class Solution {public: //第一个参数是当前处理到的工作数量,第二个参数是当前所有人中的最大工作时间 void dfs(int u,int maxn,vector<int>& jobs,int k){ //剪枝 if(maxn >= res) return;//当前已经不可能成为最优解了 //递归边.原创 2021-05-08 23:28:00 · 220 阅读 · 0 评论 -
1486. 数组异或操作
0到n-1就这样class Solution {public: int xorOperation(int n, int start) { //先求出每一位,然后依次异或,异或^相同为0,不同为1,所以一开始和0异或 int res = 0; //下标从0开始,到n-1很重要 for(int i = 0; i < n; ++i){ res ^= (start + 2*i); } .原创 2021-05-08 00:17:47 · 111 阅读 · 0 评论 -
1720. 解码异或后的数组
先将first加入数组,然后遍历encoded,每一轮将res[i]和encoded[i]做异或的结果加入res。class Solution {public: vector<int> decode(vector<int>& encoded, int first) { //xor就是异或 //异或^,相同为0,不同为1,与运算&,全1为1,其余未0,|或运算,全0为0,其余为1 //根据first慢慢推,a.原创 2021-05-08 00:16:04 · 94 阅读 · 0 评论 -
740. 删除并获得点数
评论说是打家劫舍4,很形象。这道题的题意是删除某个数字获得点数,然后强制删除i+1和i-1并且不能获得点数,我们要得到最大的点数。我们先遍历nums,记录每个数字出现的次数,并且记录下最大的数字。主要是看是否取当前数字,如果取了前面就不能取,如果没取前面就可以取,0就是没取,1就是取了状态定义:dp[i][1]就是删除当前数字,dp[i][0]就是不删除当前数字状态转移:如果取了前面就不能取(前面的被强制删除),如果没取前面就可取可不取,取了的话就=dp[i-1][0] + ima[i],用当前.原创 2021-05-08 00:13:59 · 132 阅读 · 0 评论 -
554. 砖墙
这道题要求的是穿过的最少砖块数量,用哈希表来记录间隙。unordered_map可以直接用key来移除。记录每行出现间隙的次数,比如1,2这样的,那么间隙就是1的地方出现1次,3的地方出现1次然后遍历哈希表,我们让行-出现间隙最多的次数就是穿过最少的砖块。class Solution {public: int leastBricks(vector<vector<int>>& wall) { //记录每行出现间隙的次数,比如1,2这样的,那...原创 2021-05-07 23:56:48 · 98 阅读 · 0 评论 -
403. 青蛙过河
dp的hard题,写出状态定义和状态转移都不是最难的。basecase很难,而且最好从dfs->记忆化->dp的顺序循序渐进class Solution {public: bool canCross(vector<int>& stones) { //dfs超时就考虑dp //状态定义:dp[i][k]的含义是当前在第 i 个位置,并且是以步长 k 跳到位置 i 时,是否到达最后一块石子。 //状态转移方程:根据上..原创 2021-04-29 17:40:07 · 121 阅读 · 0 评论 -
938. 二叉搜索树的范围和
利用bst的特性做,如果当前结点符合,就让sum加上当前的,并递归左右。如果当前小于low,就去右边就行了,否则就去左边。最后返回sum。一开始考虑中序遍历,很明显这样很快,O(logn),中序就是O(n)了class Solution {public: void dfs(TreeNode* root, int low ,int high){ if(root == nullptr) return; //根据low和high和val递归左边or右边 ..原创 2021-04-28 00:24:28 · 104 阅读 · 0 评论 -
1011. 在 D 天内送达包裹的能力
很好的题,一开始想dfs爆搜的,还是直接看了三叶学姐的题解。是一道二分查找的题,我们要找的是能在D天内送完的最小载重量。不考虑天数的情况下最小的载重量是足够运送最大货物的,最大载重量就是所有货物一天运完。左边界就是max,有边界就是sum,对其进行二分,写一个check函数,这个很重要,对当前运力进行判断,这是我们二分缩小搜索范围的标准。check内部就是计算当前运力需要几天运完如果运送天数<=D,mid不能扔,继续去左边找,看看能否找到更小的。如果>D,就要提升载重量,去右边找,而且..原创 2021-04-27 00:09:41 · 112 阅读 · 0 评论 -
897. 递增顺序搜索树
不用保存,直接修改cur的right就行了,但是要注意一点!!将root的left设为空,这个不会影响后序,因为root的left一定已经被访问过了/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(null..原创 2021-04-25 23:58:00 · 101 阅读 · 0 评论 -
1401. 圆和矩形是否有重叠
很久没有做到这么好的题了!!直接摘抄一下别人的解答,讲得比我好,也可以看我的注释class Solution {public: bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) { //将正方形中点看成坐标原点,把圆通过绝对值变到第一象限 //通过向量减法得到右上角的点到圆心的向量,判断这个向量和圆心的距离 ..原创 2021-04-14 00:35:20 · 146 阅读 · 0 评论 -
783. 二叉搜索树节点最小距离
两种方法,递归和迭代,总的来说就是不难,bst任意两个点的最小差,还不就是中序遍历两两相减吗?为了防止数据太恶心,我们维护的是pre结点,不是int的pre,递归就是第一次不比较,但是要更新pre为root。不管有没有更新res,pre都要在比较后更新。迭代也是一样第一次不比较class Solution {public: // void inOrderTrave(TreeNode* root){ // if(root == nullptr) return; // .原创 2021-04-14 00:31:03 · 104 阅读 · 0 评论 -
264. 丑数 II
因为丑数一定是丑数2或3或5得来的,1是第一个丑数所以我们来一个数组,定义三个指针,指向数组里的元素,一开始都指向1,然后21是最小的,所以2放到第二个,然后2这个指针++,接下来31是最小的小于22,所以3这个指针向后推进class Solution {public: int nthUglyNumber(int n) { //因为丑数一定是丑数*2或3或5得来的,1是第一个丑数 //所以我们来一个数组,定义三个指针,指向数组里的元素,一开始都指向1,然后2*.原创 2021-04-11 01:36:47 · 110 阅读 · 0 评论 -
263. 丑数
说实话一开始曲解意思了,方法1虽丑但是实用,如果一个数的两个因子,其中有一个是质数,而且不是235的话就直接false方法2是很好的方法,因为丑数不只是质因数为235,可以说它的因数只有235,30这个丑数,虽然有一对因数为2,15,但是15最后也会被拆分成35。所以我们可以把丑数认为是2i+3j+5k这样的,如果n可以整除2就一直整除,然后再对3和5做相同的操作,判断最后n是否为1就行了,为1证明是由这三个数字相乘得来的。1是第一个丑数,负数以及0不是丑数class Solution {pub.原创 2021-04-10 01:12:04 · 125 阅读 · 0 评论 -
80. 删除有序数组中的重复项 II
两种方法法一:遍历然后erase,维护一个pre作为前一个数字,和前一个数字的出现次数,如果当前和pre相等,就让cishu++,不相等就更新pre和cishu。如果cishu大于2就erase当前迭代器,记得将it–,这个很重要,而且要让cishu也–。法二:快慢指针,这个快慢指针确实niubility,我是不太想得出,慢指针是放置完的所有数据的后一位,就是待放置的位置,快指针一直猛冲,就快指针和慢指针-2比,如果相等,就让快指针++,因为慢指针-2和慢指针-1,起码有两个数字是一样的了,那么快指针.原创 2021-04-07 01:17:55 · 188 阅读 · 0 评论 -
1143. 最长公共子序列
这种题目是真正的好题。二维dp不难,难的是状压dp,记录左上的是细节,细节中的细节class Solution {public: int longestCommonSubsequence(string text1, string text2) { //字符串子序列也就是匹配问题就考虑二维dp或者滑动窗口 //滑动窗口不能确保顺序,还是得dp //状态定义:dp[i][j]代表1的前i位和2的前j位最长的匹配长度 //状态转移:多种.原创 2021-04-05 02:02:11 · 92 阅读 · 0 评论 -
面试题 17.21. 直方图的水量
接雨水原题,hard+=1。考虑每个柱子上面能接多少是最重要的,被中间两个1的柱子迷惑住了,完全不用迷惑,因为1-1就是0,那么不用在乎它的宽度了。class Solution {public: int trap(vector<int>& height) { //不就是接雨水吗,计算每个格子上方可以接多少雨水就完事了 //用单调栈,因为碰到左右都比自己的高的时候才能接 //用左右低的那个-中间的高度然后*宽度就行了 .原创 2021-04-05 02:01:08 · 122 阅读 · 0 评论 -
781. 森林中的兔子
从今天开始去牛客题霸刷题啦,leetcode开始每日一题挑战,看看能不能坚持到秋招找到好工作位置。ヾ(◍°∇°◍)ノ゙动脑筋的题,总的来说还是哈希表,但是你要知道你记录下的数字有什么用。不能简单的做,如果1的数量刚好<=2,就加上2,因为1加上自身就是2。如果1的数量大于2,比如说3,证明有1对,加一只,就是2+1+1,因为单独的这只也需要一只如果是2222,有4/3=1对,就是3只(为什么是3只,因为一对就是2+1,这是能凑成2这个数字的最小数量,如果刚好有3只兔子说和它颜色一样的有两只,它原创 2021-04-05 01:58:01 · 125 阅读 · 0 评论 -
318. 最大单词长度乘积
没啥好说的注意两个点,string的find是用来找子串的,也就是string,不是用来找char的,乖乖用substr截取一个字符串。string的find找到的话返回的是第一个匹配的下标,找不到的话是这个字符串.npos这个东西,不是返回迭代器的class Solution {public: int maxProduct(vector<string>& words) { //普通的暴力做法 //直接string的find来找就完事了.原创 2021-04-04 01:20:46 · 121 阅读 · 0 评论 -
371. 两整数之和
真的是很不错的题,注意要将a&b左移的结果转成无符号整数防止溢出(虽然我也不懂hhh)class Solution {public: int getSum(int a, int b) { //^异或,相同为0,不同为1,所以01就是1,00和11都是0,可以用来模拟没有进位的加法 //&与运算,全1为1,可以用&来算进位,&之后为1的位置证明这一位有进位,再对其<<1之后就将进位放到了应该去的位置,当完全没有进位了,就.原创 2021-04-04 01:18:56 · 97 阅读 · 0 评论 -
476. 数字的补数
笨人笨方法,注意没有前导0这个条件。特殊情况,num==0输出1补码就是对自身取反,为什么~是不对的呢,因为这是考虑了有前导0的情况的,比如2,没有前导0就是10,补码就是01,如果有前导0的情况,取补码就是1111111111111…01这样了我们先算出num有几位,然后用num来算res,将num的第一位给res的最后一位,如果第一位是1,res最后一位就是0。然后再左移res,最后res的最后一位就到第一位啦class Solution {public: int findCompl.原创 2021-04-04 01:16:48 · 114 阅读 · 0 评论 -
693. 交替位二进制数
暴力做就算了,一位一位和前面比较,不要耍小聪明一次跳两位class Solution {public: bool hasAlternatingBits(int n) { //移位运算符就行了,每次移动两位 //移动两位不行,比如0110,那么01不同,10也不同,但是11是相同的,还是得一位一位来 int pre = n & 1; n >>= 1; while(n != 0){ .原创 2021-04-03 01:14:49 · 93 阅读 · 0 评论 -
342. 4的幂
和2的幂类似,多一个条件,那就是1的出现位置是在奇数位上,可以用n%3==1来判断,n%3 ==2就是偶数位class Solution {public: bool isPowerOfFour(int n) { //首先4的幂一定是2的幂 //不用递归或者循环就是位运算 //4的幂也只有1个1,我们要在判断它是否是2的幂的情况下,判断它的1在第几位,如果在奇数位就是对的,但是要找出1在第几位,又要用循环 //可以用n%3==1来判.原创 2021-04-03 01:13:44 · 77 阅读 · 0 评论 -
231. 2的幂
没做过就做不来,做过了就做得来的easy题法一:一力降十会法二:考虑位运算,2的幂次,只有1个1,n-1之后,除了当前这个1变为0,其余全变为1,这是充要条件,如果进行&运算后为1,证明它是2的幂。tips:==的优先级大于&class Solution {public: bool isPowerOfTwo(int n) { //要不要考虑负数或者0的情况,还有小数 //负数以及0,2不管怎么样都达不到的,所以直接false .原创 2021-04-03 01:12:41 · 103 阅读 · 0 评论 -
268. 丢失的数字
1.抽屉法放回原位,但是要考虑越界和重复,越界要放在最前面判断。2.用异或来做,如果存在1,那么1 ^ 1的结果就是0,0^某个数就等于某个数,我们从0遍历到nums.size()-1,将res分别和我们需要的按顺序的数字以及实际拥有的数字做异或操作,如果我们需要的数字实际也拥有,那么同时异或就会得到0,最后剩下的就是我们缺少的。我们将res一开始设为nums.size(),这样如果都不缺,输出的就是n了class Solution {public: int missingNumber(..原创 2021-04-02 01:36:50 · 98 阅读 · 0 评论 -
684. 冗余连接
如果知道思路就好做,就是并查集(我的并查集可是刷的很猛的),不知道思路就比较难做。这道题的题意其实就是给你一个无向有环图,你怎么样删一条边,让其成为一棵树(无向无环图,顶点=边+1)。最主要就是找到这条让他们成为环的边,我们的做法就是用并查集。遍历每条边,根据find函数判断这条边的两个顶点是否处于一个连通分量,如果不处于,就用union合并它俩。如果处于同一个分量,因为没有这条边的情况下,这两个顶点就处于同一个连通分量了,加上这条边就形成环了,所以直接返回这条边就行了。class Solutio..原创 2021-04-01 01:18:29 · 110 阅读 · 0 评论 -
769. 最多能完成排序的块
维护一个值是最右端,比如43210,那么一开始的r就是4,就是从这里到下标为4的就是一整块,但是中间可能有超过4的,比如453210,那么在中间的过程中就会更新成5,那么一直到5才是一块class Solution {public: int maxChunksToSorted(vector<int>& arr) { //如果当前位置的数字不对,就一直往后找,找到应该放在这里的位置 //然后维护一个长度就是需要合成一块的数组 /.原创 2021-03-31 01:47:38 · 123 阅读 · 0 评论 -
565. 数组嵌套
暴力找环的题,重点是用一个unordered_set来记录当前数字是否被访问过了,如果没有就继续往后,如果被访问过了,就结束这条路径的查找,用当前路径长度来更新maxnunordered_set是全局的!!不是局部的,不是每次来一个新起点就维护一个unordered_set,全局的话就可以记录013这种路径,你到1就不会再次进入这次循环了,因为这是重复搜索了class Solution {public: int arrayNesting(vector<int>& nums.原创 2021-03-31 01:46:31 · 132 阅读 · 0 评论 -
766. 托普利茨矩阵
反正挺恶心一道题,你想要对它进行优化就会发现一些坑。老老实实只和自己右下角的比就行了,不要一条路走到黑,这样会有很多重复判断class Solution {public: bool isToeplitzMatrix(vector<vector<int>>& matrix) { //暴力遍历 int row = matrix.size(); int col = matrix[0].size(); ..原创 2021-03-31 01:40:50 · 87 阅读 · 0 评论 -
785. 判断二分图
先说一下二分图的定义:1.两个子集内的顶点都不相交2.两个点集包含了所有点用了两种图的遍历方法,其实都是染色法,解释都在注释里法一:BFSclass Solution {public: bool isBipartite(vector<vector<int>>& graph) { //1.两个子集内的顶点都不相交 //2.两个点集包含了所有点 //两个连通的顶点要放到不同集合里,如果同一个集合的顶点是连通...原创 2021-03-31 01:39:12 · 125 阅读 · 0 评论 -
697. 数组的度
和数量有关的子序列,当然是滑动窗口,而且是比较简单的滑动窗口。滑动窗口,如果某个窗口新加了r之后,如果达到了maxn,就缩减左边,缩减到window[r]不为maxn为止,每次在中间就要进行判断r-l+1和maxn谁更小,这个很重要,不是在外面判断的class Solution {public: int findShortestSubArray(vector<int>& nums) { //滑动窗口,如果某个窗口新加了r之后,如果达到了maxn,就缩减左边.原创 2021-03-30 01:37:19 · 90 阅读 · 0 评论 -
667. 优美的排列 II
dfs全排列是我写的,数学的看不懂,也不想看!class Solution {public: // void dfs(int n, int k,vector<int> tmp){ // if(res.size() != 0) return; // if(tmp.size() == n){ // unordered_set<int> qujian; // for(int i = 0; i &l.原创 2021-03-30 01:35:12 · 135 阅读 · 0 评论 -
645. 错误的集合
法一:用哈希记录每个数字出现的次数,从1到n再次遍历,如果有出现次数为0的,这个数就是缺的,如果有等于2的,就是多。法二:(明天看)还是可以用抽屉法的,放回自己的原位,如果原位上已经放了自己的复制体就跳过,再次遍历,如果位置不符合,就直接返回这个数和这个位置class Solution {public: vector<int> findErrorNums(vector<int>& nums) { //用哈希记录每个数字的出现的次数 .原创 2021-03-30 01:32:13 · 117 阅读 · 0 评论 -
485. 最大连续 1 的个数
还是一样,最后更新一下maxn,因为可能最后以连续1结尾,那么就没碰到0,就不更新maxn了class Solution {public: int findMaxConsecutiveOnes(vector<int>& nums) { int maxn = 0; int tmp = 0; for(int i = 0; i < nums.size(); ++i){ if(nums[i] != 1){.原创 2021-03-29 01:20:58 · 90 阅读 · 0 评论