LeetCode
文章平均质量分 57
每天至少更新一篇LeetCode题解
王江奎
这个作者很懒,什么都没留下…
展开
-
Leetcode第314场周赛
Leetcode第314场周赛总结原创 2022-10-10 14:03:02 · 335 阅读 · 0 评论 -
Leetcode第 313 场周赛
Leetcode第 313 场周赛总结原创 2022-10-03 12:41:31 · 425 阅读 · 0 评论 -
850. 矩形面积 II:扫描线+离散化+线段树
Leetcode 850. 矩形面积 II原创 2022-09-19 10:23:47 · 462 阅读 · 0 评论 -
Leetcode第309场周赛
Leetcode第309场周赛总结原创 2022-09-05 22:36:03 · 805 阅读 · 0 评论 -
每日一题:449. 序列化和反序列化二叉搜索树
题目分析题目链接:449. 序列化和反序列化二叉搜索树觉得序列化很简单,前序遍历、后序遍历、中序遍历、层序遍历等等。其中得到前序遍历和后序遍历是可以通过递归解法反序列化的,觉得这样子做有点复杂。就想着可不可以一次遍历。一次遍历的问题在于不知道哪里子孩子为空(因为没有保存子孩子为空的情况)。所以我就针对性地让空节点的值为-1。为了方便从字符串中读取数字,使用了C++中的istringstream。整体的实现还是比较简洁高效的。实现代码class Codec {public: // Enco原创 2022-05-11 21:36:45 · 212 阅读 · 0 评论 -
第288场周赛
绪论虽然没有AK,但是不知道为什么排名比以前AK了都靠前。可能是因为最后一道题有些难度,缩小了我和大佬之间的差距。最后一个小时写最后一道题,累死累活想了一个贪心遍历的算法,当时是一直RE,后来下来调了调又WA了。题目分析A: 按奇偶性交换后的最大数字做法就是用一个数据结构去保存奇数数字和偶数数字,要求这个数据结构能够返回并弹出最大值。当时没有仔细考虑,直接用了一个multiset去保存,因为红黑树本身就是有序的,所以每次弹出最后一个节点。但是因为把前置–写成后置–了,所以还RE了一发,实在不应该。现原创 2022-04-11 22:23:00 · 387 阅读 · 0 评论 -
第287场周赛
绪论虽然是上周日参加的比赛,但是这周没有怎么学习,每天就是玩耍。也导致对周赛的总结迟迟没有进行。想着再拖下去下次周赛都要开始了,在这里补一下。这场比赛总体比上场简单一些,但是最后一道题因为忘记初始化类内变量导致调试好久,血泪教训。题目分析A:转化时间需要的最少操作数因为单独考虑小时、分钟太过繁琐,我的方法是将其转换成时间戳(类似chrono的time_since_epoch方法)。class Solution {public: int convertTime(string curre原创 2022-04-08 10:37:41 · 911 阅读 · 0 评论 -
Leetcode第286场周赛
绪论上周因为有事没有参加周赛,这周没有错过。这次周赛拿到了人生第一个AK,参加大大小小的比赛这么多次,从来没有AK过,泪目了。感觉这次比赛的思维难度对我来讲稍高一些,前三道题就花了一个小时,而以往只需要半个小时。看了一下排名前面的大牛们,还是十分钟就AK了,深觉自己还马达马达大内。题目分析比赛链接:https://leetcode-cn.com/contest/weekly-contest-286/题目难度上第二题和第三题都有一些思维量,不像以前直接模拟。第四题我直接记忆化搜索在最后一分钟过了原创 2022-03-28 14:20:42 · 644 阅读 · 0 评论 -
Leetcode第284场周赛
绪论最近发现Leetcode每周的周赛难度挺适合我的,而且时间也比较友好(不像Codeforces每次都是半夜)。所以连续参加了三周的周赛。这次才想起来应该记录一下自己的参赛历程。一方面是总结经验,另一方面有了记录就更有动力去提升,去参加下一次比赛。题目分析题目链接:https://leetcode-cn.com/contest/weekly-contest-284/还是往常一样四道题,难度依次提升。A:找出数组中的所有 K 近邻下标简单模拟,对于每一个key,其附近的2k+1个元素都是合法的原创 2022-03-14 10:32:27 · 926 阅读 · 0 评论 -
leetcode869. 重新排序得到 2 的幂
题目连接:https://leetcode-cn.com/problems/reordered-power-of-2/题目分析如果直接顺着题目的思路,得到数字n的全排列,然后再去判断其是不是2的幂是比较复杂的。我们应该注意到,因为数字是可以随意排列的,因此所有可以通过变换排列得到的数字都有相同个数的0、1、2,而n⩽1e9n\leqslant1e9n⩽1e9,2的幂只有30个左右,我们可以先记录2的幂次然后再判断当前数字是不是和这些数字有相同的数字组合。AC代码class Int { st原创 2021-10-28 10:42:01 · 123 阅读 · 0 评论 -
每日一题:leetcode81.搜索旋转排序数组Ⅱ
题目描述题目分析不含重复元素的题解(leetcode33)这道题也是我们算法课的一道编程题,写完以后发现当时的思路和现在没有什么变化,果然是自己啊。我的想法是先判断区间整体是升序的还是旋转的,如果是升序的就按照正常的二分查找,如果是旋转的就判断中轴的落在了左半升区间还是右半升区间,问题的关键在于,旋转的数组不能简单因为target和中轴的大小判断是在左区间还是右区间,因此要分类讨论一下。总之,这个思路不是很好,因为没有有效利用端点的信息,如同官方题解所说,我们是可以直接判断出target在哪个区间的原创 2021-04-08 00:32:42 · 148 阅读 · 0 评论 -
每日一题:leetcode80.删除有序数组中的重复元素贰
题目描述题目分析又是一道贴错标签的简单题,很明显的双指针,我的做法是用两个变量保存是否需要记录,官方题解的做法是直接判断,人家的高明一些class Solution {public: int removeDuplicates(vector<int>& nums) { int n = nums.size(); if (n < 3) return n; int i = 0, j = 0, cnt = 0, now = I原创 2021-04-06 12:21:09 · 159 阅读 · 0 评论 -
每日一题:leetcode1006.笨阶乘
题目描述题目分析因为顺序一定且没有括号,所以逻辑很简单。我们要顺序处理的矛盾在于,减号后面会再出现乘法和除法,我们不妨将对乘法和除法用一个临时值进行计算,计算结束后再合并到值里面,一般来讲乘法和除法的处理结果是一个负数,例外是刚开始出现的乘法和除法,我们特殊判断一下,其他的就顺序处理。需要注意的是最后循环结束后我们还要再将临时量合并到值里面,因为有可能没有到除法,没来得及合并。具体可以看代码,很好理解:class Solution {public: int clumsy(int N) {原创 2021-04-01 10:37:49 · 166 阅读 · 0 评论 -
每日一题:leetcode90.子集贰
题目描述题目分析感觉这道题让自己对枚举排列有了一个更好的认识,感觉自己的这种思路不错。假设没有重复元素(退化成78.子集),我们应该怎么做?初始的时候幂集中只有一个空集,然后对每个元素,我们添加给幂集中的每个元素,这样进行一遍遍历,复杂度是O(1)+O(2)+O(4)+...+O(2n−1)=O(2n)O(1)+O(2)+O(4)+...+O(2^{n-1})=O(2^n)O(1)+O(2)+O(4)+...+O(2n−1)=O(2n)对于有重复元素的我们应该如何处理呢?不难发现,假设我们把重复元原创 2021-03-31 23:49:49 · 172 阅读 · 0 评论 -
每日一题:leetcode74.搜索二维矩阵
题目描述题目分析感觉这是一个放错标签的简单题。题目非常简单,思路应该很明确是二分,我很快写了一个(虽然不小心把!=打成==调试了一会)。class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { if (target < matrix[0][0] || target > matrix.back().back()) retu原创 2021-03-30 10:58:30 · 157 阅读 · 0 评论 -
每日一题:leetcode190.颠倒二进制位
题目描述题目分析题目本身很简单,没觉得有什么技巧可以再进行优化了,觉得位运算是无法打乱相对顺序的,而这里需要进行镜像颠倒的操作。因此就踏实地写了一个循环。在使用位运算得到每一位的时候,我吸取了经验,用一个临时变量保存,这样每次只用进行一次移位操作,这样是一个小小的优化。class Solution {public: uint32_t reverseBits(uint32_t n) { uint32_t ans = 0; uint32_t t1 = 1 &l原创 2021-03-29 13:59:29 · 167 阅读 · 0 评论 -
leetcode11.盛最多水的容器
题目描述题目分析看到题目后第一个想法当然是O(n2)O(n^2)O(n2)的,但是数据范围是3e4,应该会超时,而且这种数据范围也不是让暴力求解的 。相当于求解∑i<jmax((j−i)∗min(a[i],a[j]))\sum_{i<j}{max((j-i)*min(a[i],a[j]))}∑i<jmax((j−i)∗min(a[i],a[j]))。因为minminmin的缘故,所以我觉得不能进行区间合并。总之没有什么头绪。看了题解以后发现这是一道数学题,策略: 初始时用两个指原创 2021-03-29 00:19:27 · 127 阅读 · 0 评论 -
每日一题:leetcode173.二叉搜索树迭代器
题目描述题目分析更加地觉得编程重要的不在于如何写代码,用什么具体的技巧,编码本身只是一种将思维呈现的方式,但是如果思维是不清晰的,那么就算懂得再多的编码的奇技淫巧也是没有什么帮助的。相反,如果有一个清晰的思路,便能很轻松的写出优雅的代码。最近在看《编程大师访谈》,感觉很多大师都提到的一个思想:编程最重要的是数学而不是代码本身。他们觉得本科教育完全不应该接触计算机,而是应该学习数学、历史等知识。我刚进大学的时候觉得学习高数、大学物理没有丝毫意义,现在慢慢觉得那些知识对思维的训练的重要程度比什么所谓的专业原创 2021-03-28 11:09:36 · 141 阅读 · 0 评论 -
每日一题:leetcode61.旋转链表
题目描述题目分析很容易发现,如果k是n的整数倍,相当于没有移动。这样直接对k%n使得k在一个可以接受的范围。因为是顺序移动,各元素之间的相对位置保持不变,所以就想着将链表先变成一个环。然后再移动头指针,最后再断开。头指针我们只能向后(右)移动,但是头指针的向右移动相当于整个链表向左移动,因此我们要将头指针移动n-k次,这样和向右移动k次链表的效果相同。得到头指针后我们再将链表断开。我这里用了一种比较笨的方法,是在头指针的基础上再移动链表的长度,看题解才发现,原来尾指针就在头指针的前面,我只要保存原创 2021-03-27 10:38:51 · 140 阅读 · 0 评论 -
leetcode283.移动零
题目描述题目分析在写简单题放松,看到这道题第一个想法是用STL库函数,虽然知道大概要用双指针之类的,但是库函数爽哇。class Solution {public: void moveZeroes(vector<int>& nums) { stable_sort(nums.begin(), nums.end(), [](const auto &a, const auto &b) -> bool { if (a原创 2021-03-26 17:59:36 · 114 阅读 · 0 评论 -
每日一题:leetcode456.132模式
题目描述题目分析我觉得这道题应该是我做过最难的中等题之一了,这是昨天的每日一题,但是昨天用nlogn的做法做出来以后在看题解,发现有些看不懂(觉得题解有点故弄玄虚)。然后今天中午又花了一点时间才搞懂,感觉从这道题里面学到一点东西。刚拿到这道题的时候我没有什么思路,第一想法当然是n3n^3n3的暴力,但是显然是不行的,第二想法是,用线段树维护区间最大值,然后遍历1和2,这样的复杂度是n2lognn^2lognn2logn,虽然好了一点但仍然会超时。我自己没有想到枚举一个,然后通过数据结构求其他两个的思原创 2021-03-25 14:10:21 · 190 阅读 · 0 评论 -
每日一题:leetcode82. 删除排序链表中的重复元素 II
题目描述题目分析这才是正常的中等题难度嘛,昨天的中等题题解我半天看不懂。。。首先,需要增加一个哑节点(操作链表的常规操作),因为有可能删除首节点,我们不想要为首节点添加单独的逻辑。其次,用一个变量保存前驱节点,因为删除操作必须要前驱节点,初始化为哑节点。我的想法是,用一个指针指向一个元素开始的地方,另一个指针指向重复元素结束的地方,如果两个指针相等,说明没有重复元素,则将前驱节点后移,如果不相等,说明需要进行删除。没有考虑对空间的释放,因为不知道链表是怎样生成的,如果是new出来的要考虑dele原创 2021-03-25 11:11:39 · 283 阅读 · 0 评论 -
每日一题:leetcode341.扁平化嵌套列表迭代器
题目描述题目分析这个题目自己大概花了一个小时,虽然是一遍AC,但是速度有点慢,太长时间不写代码导致自己对代码不太敏感,写起来慢腾腾的。看到这个的想法就是,要用栈来保存列表的迭代器,这样将孩子列表遍历完成后才能重新回到父亲列表中,如果栈为空当然就结束了。首先是对函数调用的分析,会首先调用hasNext再调用next,这就要求我们如果把后移操作放到hasNext中,那么栈顶就要指向当前位置之前,对于迭代器来说不容易操作,因此我们决定将后移操作放到next函数中首要要定义栈中保存的迭代器的含义:我的想原创 2021-03-23 13:30:26 · 136 阅读 · 0 评论 -
每日一题:leetcode191.位1的个数
题目描述题目分析很自然地想到了二进制枚举,直接循环检查每一个二进制位。class Solution {public: int hammingWeight(uint32_t n) { int ret = 0; uint32_t t = 1; for (int i = 0; i < 32; ++i, t <<= 1) { if (n & t) { ++ret;原创 2021-03-22 22:10:46 · 116 阅读 · 0 评论 -
每日一题:leetcode724.寻找数组的中心索引
题目描述题目分析今天这道题原本很简单,我都没打算写题解,当时用手机看的题目,我想着我三分钟应该能写出来,结果没想到wa了三发。。。对待简单题不要轻视,对待难题不要畏难。今天的主要问题是没有看数据范围,虽然只是一道很简单的题,但是自从刷力扣以来自己基本不怎么关注数据范围、边界条件,总是等报错以后才去看,这是一个很差劲的习惯,实际编程环境中是不会有现成的数据供测试的。没有看到题目中数组可能为空,而没有想到中心索引可以是最左侧或者最右侧的。AC代码class Solution {public:原创 2021-01-28 15:20:28 · 151 阅读 · 0 评论 -
每日一题:leetcode1579.保证图可完全遍历
题目描述题目分析非常惭愧,感觉自己有点畏难心理,看到是困难题第一个想法是自己想不出来。。。因为自己认为自己做不出来,所以完全不能进行思考,稍微思考一下就觉得不行不行。我也想到了分别用两个并查集判断各自可以去掉多少边,但是一想到还有公共边,就感觉一头乱麻,不知道从什么地方下手。当时主要感觉困难的地方在于,如果两个人去掉的公共边不一样,则没有办法统一。看了题解以后我觉得我这个想法离正确的思路已经非常近了,抓住公共边这个矛盾再进行思考应该就可以。另一方面还应该有跳出思维定势的能力,不能因为题目中先原创 2021-01-27 17:04:13 · 136 阅读 · 0 评论 -
每日一题:leetcode1128.等价多米诺骨牌对数
题目描述题目分析看到题目以后第一个想法是遍历数组,对每个元素有一个数据结构中保存了该元素出现的次数,然后往结果中相加(表示该元素和前面的对数),然后再将元素出现的次数加一。思考用什么数据结构保存元素出现次数的时候想到用线性哈希,看到数据最大不超过10,那么就用10∗x+y10*x+y10∗x+y即可。这样很容易获得所有牌出现的次数。这个时候我懒得每次往结果中加元素了。如果很容易获得牌出现的次数n,想要得到有多少对,即就是Cn2C_{n}^{2}Cn2。看了题解以后,我觉得应该我这样的做法复杂度原创 2021-01-26 10:53:48 · 140 阅读 · 0 评论 -
每日一题:leetcode1319.联通网络的操作次数
题目描述题目分析ps:这篇博客是补前天的,前天在老家不方便写博客题目挺简单的,但是通过题目对图的连通性有了一个更深刻的认识:如果有超过(或等于)n-1条边,则一定是可以让整个图联通的。如果想让整个图联通,只需要求出整个图的联通分量个数,然后-1就是需要的边的个数(即让这写联通分量联通即可)AC代码class UnionFind {public: vector<int> father; vector<int> size; int n; i原创 2021-01-25 14:53:57 · 236 阅读 · 0 评论 -
每日一题:leetcode959.由斜杠划分区域
题目描述题目分析仔细分析这道题以后虽然觉得可能要转化为图之类的,但是完全没有具体的想法,因为每个格子都有三种情况,这三种情况的不同的组合又会产生不同的结果。发现找不到编码转化为图以后,我分析了一下不同数量方块之间的联系,试图找到像递归一样的关系。发现也没有找到,关键是边长小的方块四周会有边,但是将其放到大方块中并没有这些边,而且他们的边界还会组合。在没有思路之后我看了一下题解,发现题解最巧妙的地方在于将每一个单元块再次划分为四个小块,从而将原先三种情况统一了起来:每种情况是这四个小块的不同组合方式原创 2021-01-25 14:43:13 · 132 阅读 · 0 评论 -
每日一题:leetcode674.最长连续递增序列
题目描述题目分析一遍遍历,如果硬要说用了什么算法的话觉得应该算是一个简单的滑动窗口吧AC代码class Solution {public: int findLengthOfLCIS(vector<int>& nums) { if (nums.size() == 0) { return 0; } int ret = 1; int cnt = 1; for (int i原创 2021-01-24 20:35:52 · 127 阅读 · 0 评论 -
每日一题:leetcode989.数组形式的整数加法
题目描述题目分析题目非常简单,但是我还是wa了几发,对不起,我太菜了。我的想法是把K转换为数组然后用大整数加法处理。但是因为太久没有写了导致写了好久。class Solution {public: void add(vector<int> &A, vector<int> &B) { int len_A = A.size(); int len_B = B.size(); for (int i = 0; i原创 2021-01-22 17:53:22 · 122 阅读 · 0 评论 -
每日一题:leetcode1489. 找到最小生成树里的关键边和伪关键边
时隔多年我终于又开始写博客了,主要是已经放假了,之前一直忙于考试和课设没有时间写博客,学习笔记也因为买了iPad的缘故大部分都是手写的了。假期想要把以前做过的项目都整理一下放在github和CSDN上。也已经很久没有写算法题了,直接导致今天这道题虽然我看了题解但是自己还是写了好久。题目描述传送门题目解析题解有两种解法,第二种我直接没有看,因为Tarjan算法我已经忘光了,而且这道题好像还用到了kraskal算法的一个性质(并不知道在Kruskal 算法中,对于任意的实数 w,只要我们将给定原创 2021-01-22 00:02:30 · 218 阅读 · 0 评论 -
327 区间和的个数
题目描述Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.Note:A naive algorithm of O(n2) is trivial.原创 2020-11-08 00:24:11 · 145 阅读 · 0 评论 -
链表三连击
876:链表的中间节点206:反转链表143:重排练表链表的中间节点这个题一看就是最简单的快慢指针,但是在具体实现的时候我还是犹豫思考了一下:要不要在链表前面放置哑节点,快指针应该什么时候判断已经到达结尾。但是单纯的想并没有什么结果。对于这种不是算法本身的问题,而只是实现细节的问题,不要多想,没有很大的意义,只要对于每种情况都动手(脑)模拟一遍,看这么样能够让情形变得更加简单即可。我思考了一下以后写了一下自己的代码:/** * Definition for singly-linked list原创 2020-10-20 23:09:33 · 190 阅读 · 0 评论 -
844. Backspace String Compare
题目的意思大概是有两个字符串,其中的#表示退格键,让比较最后两个字符串是否相当。很容易想到的思路就是用一个栈进行模拟这个过程,特别需要注意如果一个串是空串也是可以退格的。但是很容易想到的另一个特性就是,前面的字符有可能被后面的退格符删去,但是如果如果从后往前进行遍历的话那么一个字符一旦保留就不会被删除,我们比较两个字符串保留下来的字符,一旦发现不相等就直接返回。总体来讲就是双指针加逆序遍历。其实看到这个题我直接就想到双指针加逆序遍历了。但是昨天晚上也不知道是因为困了还是什么原因,写了二十分钟写的都是原创 2020-10-20 13:48:32 · 141 阅读 · 0 评论 -
19 删除链表的倒数第N个
题目的意思很简单,就是删除一个链表倒数第N个节点。需要用到链表的标准操作:快慢指针。我们让一个快指针先指向第N个元素,这个时候快指针总比慢指针领先N个元素,等到快指针指向链表尾部的时候慢指针就指向需要删除的元素。之前已经用了几次了(比如空间复杂度O(1)O(1)O(1)判断链表是否有环以及环的位置),但是我看到这道题竟然还是一下没有想到。顺带忏悔一下,之前说好每天至少一道题解的,但是前面忙其他的事就没有弄了,罪过罪过,后面要继续坚持。看到提接学到链表的一个操作:哑指针。因为我们一般得到的都是链表的原创 2020-10-19 00:01:17 · 77 阅读 · 0 评论 -
141 环形链表
要求使用空间复杂度为O(1)的方法,可是我并没有想到。我想到的只有用一个哈希表记录一下所有访问过的节点。题解给出的空间复杂度为O(1)的方法是使用两个指针,然后让一个一次跑一步,一个一次跑两步,如果跑的快的能追上跑的慢的就是有环,如果跑得快的跑到了链表的末尾就是没有环。设置跑的快的比跑的慢的多跑一步,这样对一个长度至多为N的环,总会追上的,时间复杂度为O(N)。需要注意处理循环条件,并且因为跑的快的节点每次要跑两步,要处理如果没有环跑的快的节点跑一步就跑到结尾的情况。/** * Definition原创 2020-10-09 13:32:40 · 95 阅读 · 0 评论 -
75 颜色分类
题目已经提示可以一遍扫描了但是我还是没有想到,其实双指针的想法我已经有了,但是一想到有问题就觉得无法实现。这也揭示了我思维上的问题:用一种方法解决问题遇到困难第一件事情不是想着如何攻克而是想着换一种方法。对自己的思维也不自信。我自己简单了写了一个两遍扫描的程序:class Solution {public: vector<int> cnt; void sortColors(vector<int>& nums) { cnt.resize(3,原创 2020-10-08 10:37:05 · 161 阅读 · 0 评论 -
834 树中距离之和
这道题我自己的想法只有对每个点都用一遍Dijkstra然后再求和,显然会超时,所以我都没有尝试。研究了一下题解,发现题解很巧妙,自己对树的处理还是太稚嫩,之前树链剖分学的都忘光了。对于固定根节点的,我们应该使用树状dp:dp[u]=∑v∈son(u)dp[v]+sz[v]dp[u]=\sum_{v\in son(u)} dp[v]+sz[v]dp[u]=v∈son(u)∑dp[v]+sz[v]其中,dp[u]dp[u]dp[u]表示以u为根节点的子树中根节点u到其儿子节点的所有距离之和,之所以原创 2020-10-06 18:28:16 · 154 阅读 · 0 评论 -
1 两数之和
虽然只是一道很简单的题,但是也给我很多思考。刚看到这道题的时候没有仔细思考,直接写了个排序和二分查找,想着对每个数字查找另一个数字会不会出现,复杂度是O(nlogn+nlogn)O(nlogn+nlogn)O(nlogn+nlogn),主要训练了一下自己手写快速排序和二分查找。class Solution { void swap(vector<int>& a,vector<int>& b,int i,int j) { int t=a原创 2020-10-06 17:14:06 · 161 阅读 · 0 评论