Leetcode
CodeLuweir
壁立千仞,无欲则刚!
展开
-
Leetcode动态规划:300.longest-increasing-subsequence(最长递增子序列)
300. 最长递增子序列最近一直在攻克动态规划的题,Leetcode的简单题已经刷完,现在冲中等题,这道题算是一个比较经典的题吧,独立完成,虽然花了两个多小时,但收获很多;思路:动态规划首先要找到状态,其次建立状态转移方程;此处状态无疑就是当前子序列的长度以及子序列的尾数,因为这样才能动态改变状态,比较来了一个大的数字,我可以让子序列长度+1,然后把子序列的尾数更新为它,当然这只是个简单思路,里面还有很多细节问题;int lengthOfLIS(vector<int> &num原创 2021-01-22 22:04:42 · 264 阅读 · 0 评论 -
Leetcode每日一题:989.add-to-array-form-of-integer(数组形式的整数加法)
这道题还是要写一下思路:首先想到的就是把数组转换成数字,直接相加,因为A的长度只有10000,但后来明显越界了,行不通;后来想到把K逐位加到A上,但很复杂,最终采用以下方法;vector<int> addToArrayForm(vector<int> &A, int K){ int len = A.size(); if (K == 0) return A; int flag = 0; //进位 int index = len - 1; vector&原创 2021-01-22 10:43:45 · 213 阅读 · 0 评论 -
Leetcode每日一题:290.word-pattern(单词规律)
思路:hash索引肯定要用的,但这道题我既要让单词对应字符,也要判断这个单词所对应的字符是否已被别的单词对应,所以我用了两个map,方便判断;一个是map<string,char>,一个是map<char,string>;bool wordPattern(string pattern, string s){ int len = s.size(); map<char, string> m1; map<string, char> m.原创 2020-12-16 10:43:51 · 253 阅读 · 0 评论 -
Leetcode每日一题:738.monotone-increasing-digits(单调递增的数字)
思路:从后向前遍历,如果当前数字比下一个数字大,就把当前数字-1,并把后面所有数字变成9;这样能保证递增且最大;这里把数字转换成string方便循环修改;int monotoneIncreasingDigits(int N){ if (N / 10 == 0) return N; string s = ""; int n = N; //将数字转换成string while (n) { s.insert(s.begin(.原创 2020-12-15 09:06:22 · 216 阅读 · 0 评论 -
Leetcode每日一题:面试题17.12 binode
面试题 17.12. BiNode二叉树的中序遍历是弱项,需要额外练习,特别是二叉搜索树的中序遍历,利用它是递增数列的性质;通过一个pre来不断地修改节点指向,有左节点优先左节点,没有则右节点,pre指向的是当前节点在中序序列中的前一个节点;TreeNode *pre = nullptr;void biNode(TreeNode *cur){ if (!cur) return; biNode(cur->left); if (pre == nul原创 2020-12-13 11:02:57 · 245 阅读 · 0 评论 -
Leetcode每日一题:217.contains-duplicate(存在重复元素)
今天的一道简单题,还算人性,最近一直都是动态规划、贪心这些;方法一:用hash为每一个值建立键值对,在遍历数组元素时,如果这个键值对已存在,说明这个元素重复出现了;方法二:用set集合,因为集合不包含重复元素,把nums所有元素丢进去,如果set的长度和nums的长度不一样,说明有重复元素;//hashclass Solution {public: bool containsDuplicate(vector<int>& nums) { unorder.原创 2020-12-13 09:52:52 · 263 阅读 · 0 评论 -
Leetcode二叉树&递归:563.binary-tree-tilt(二叉树的坡度)
思路:就是一个二叉树的遍历,不过注意,我们要在遍历过程从对每个节点计算坡度abs(left-right),并加到res中,但我们不能return res,因为坡度的定义是左子树的节点之和与右子树的节点之和的差的绝对值,所以递归时我们要返回return left+right+root->val;为什么这样就能保证left和right就一定表示左右子树的节点和呢?因为当我们递归到叶子节点,叶子节点没有子节点,若以它们的left和right都为0,那么此时就会返回它们自己的节点值,这样递归上去就是;...原创 2020-12-12 13:25:23 · 362 阅读 · 0 评论 -
Leetcode每日一题:376.wiggle-subsequence(摆动的序列)
class Solution {public: int wiggleMaxLength(vector<int>& nums) { if (nums.size() == 0) return 0; int nLength = 1; int nState = 0; //为1表示上升,为-1表示下降,为0表示元素不够 for (int i = 1; i < nums.size(); ++i) {..原创 2020-12-12 09:44:37 · 245 阅读 · 0 评论 -
Leetcode每日一题:649.dota2-senate(Dota2参议院)
法一:朴素法,也是看完题后最先想到的,从头开始对于每位议员i,从i的后面开始循环找到i的首个未被禁言的敌人j,并把它的rec[j]置为0,表示被禁言;只有rec[i]!=0的时候,才说明i未被禁言,才能进入循环发挥i的权利;如果某次循环中找不到i的敌人了,那么说明i阵营胜利;string predictPartyVictory(string senate){ int len = senate.size(); vector<bool> rec(len, 1); wh.原创 2020-12-11 08:54:09 · 259 阅读 · 0 评论 -
Leetcode每日一题:860.lemonade-change(柠檬水找零)
思路:初始化手上已有的五元钱和十元钱的数量count5=0,count10=0;然后遇到5元,count5++;遇到十元,判断count5>0?;遇到20元,判断count10>0&&count5>0或者count5>=3;如果遇到10元或者20元有任意情况不满足,直接返回false;class Solution {public: bool lemonadeChange(vector<int> &bills) { .原创 2020-12-10 08:27:37 · 200 阅读 · 0 评论 -
Leetcode每日一题:62.unique-paths(不同路径)
思路:一开始用的BFS,超时了,感觉这题可以用数学方程做,但懒得推理了,直接用的动态规划;算是动态规划入门题吧;path[i][j]表示点(i,j)到重点的不同路径个数,那么path[i][j]=path[i+1][j]+path[i][j+1],一开始处理边界,最后一列和最后一行都置为1,因为它们到终点只有一条路径,然后用方程即可;//动态规划int uniquePaths(int m, int n){ if (m == 1 && n == 1) retu.原创 2020-12-09 08:35:19 · 249 阅读 · 0 评论 -
Leetcode每日一题:842.split-array-into-fibonacci-sequenc(将数组拆分成斐波那契序列)
思路:深度优先搜索,设定最后返回的数组vec,每次搜索只处理一个数,这数可以取1位,也可以取很多位,这取决于前面两个放入vec的数的和(vec只有两个及以下的数时,直接放入),如果无法等于他俩的和,那么这个数没用,并且前一个数应该继续尝试新的数(这里就是回溯);如果遍历到最后我的vec中还有三个以上的数,则说明可行;//当前处理元素S[i]开始若干字符,如果能够与sum相等,继续处理下一部分元素,否则返回false,清除vec后面的元素bool dfs(vector<int> &.原创 2020-12-08 09:40:14 · 461 阅读 · 0 评论 -
Leetcode每日一题:861.score-after-flipping-matrix(反转矩阵后的得分)
思路:二进制一个高位为1比之后所有低位为1所代表的数字都要大,所以首先要确保每一行的第一位为1,然后在这基础上对于每一列,如果零的个数多于1的个数,将这列翻转;static int dec(vector<int> a){ int fac = 1, res = 0; int len = a.size(); for (int i = len - 1; i >= 0; i--) { res += a[i] * fac; fa.原创 2020-12-07 12:18:07 · 196 阅读 · 0 评论 -
Leetcode每日一题:659.split-array-into-consecutive-subsequences(分割数组为连续子序列)
思路:看它贴的标签是贪心算法,我只想到了记录每个数出现的个数,并且还是数组,后来一想如果元素太大导致数组长度很长怎么办,老是想不到hash的方法,也没想到记录以nums[i]结尾的连续子序列个数;贴上大佬的回答:这里一定不要把tail[nums[i]+1]、tail[nums[i]+2] 和tail[nums[i+1]]、tail[nums[i+2]]混淆;class Solution {public: bool isPossible(vector<int> &n.原创 2020-12-04 10:44:37 · 240 阅读 · 0 评论 -
Leetcode每日一题:767.reorganize-string(重构字符串)
思路:这道题还是有难度的,我只想到了如何判断它是否为空字符串,而不知道非空字符串时应该输出的结果,就是没有想到插入法;这道题可以通过举例子发现,如果最大的字符个数如果>(长度+1)/2,那么它是无论如何都达不到条件的;可以通过计算每个字符出现个数来实现这一功能;举个例子就能发现,如果length=3的字符串aab对于出现(length+1)/2次的a字符,只能把它放在evenIndex才能装下(主要就是因为第一个索引为0),并且这个字符串是满足条件的;总的来说,就是一定要想到插入法,想明白为.原创 2020-11-30 20:43:47 · 212 阅读 · 0 评论 -
Leetcode每日一题:976.largest-perimeter-triangle(三角形的最大周长)
思路:首先肯定是排序,排序后只需要从一个方向上开始找即可;但这里我用的二分查找,确定A[i]和A[i-1]后我们需要在后面找一个数x,使得x为<A[i]+A[i+1]的最大的数,所以这种东西秒想到二分查找;后来通过后看评论,排序后直接从数组尾部开始遍历即可,因为要找最大的周长,并且A[i]肯定是>(A[i-1]-A[i-2])的,所以只需要找到某个A[i],它能够满足A[i]<A[i-1]+A[i-2]即直接就是最大的周长;速度还有有差别的//法1://在a[l]和a[r]之间找.原创 2020-11-29 13:35:04 · 252 阅读 · 0 评论 -
Leetcode刷题系列汇总
分治 && 归并原创 2020-11-28 10:44:21 · 356 阅读 · 0 评论 -
Leetcode每日一题:493.reverse-pairs(翻转对)
官方题解给出的解题思路还是比较清晰的,分治到不能再分后,开始分别计算两个子序列各自的翻转数,然后归并:归并后的翻转数=二者各自翻转数之和+两个子序列之间可能构成的翻转对(两个循环即可求出);然后排完序继续归并,规模不断扩大;class Solution {public: int reversePairs(vector<int> &nums, int left, int right) { // 边界条件:分到只有一个元素了,重要翻转对数为0 .原创 2020-11-28 10:43:40 · 343 阅读 · 0 评论 -
Leetcode每日一题:面试题17.10.find-majority-element-lcci(主要元素)
思路:这道题不是单纯的摩尔投票法,因为它有可能不存在主要元素,而摩尔投票要求必须存在主要元素;这里通过摩尔投票法得到的可能是那个渔翁得利的元素,比如2 2 3 3 1,那么最后res=1,但实际上这个数组并不存在主要元素,所以这就需要我们再对数组遍历一次,看看res是不是主要元素;int majorityElement(vector<int> &nums){ int len = nums.size(); int res = nums[0], count = 1.原创 2020-11-27 13:10:38 · 230 阅读 · 1 评论 -
Leetcode每日一题:454.4sum-ii(四数相加Ⅱ)
思路:四个循环肯定会超时的,1、遍历 A 和 B 所有元素和的组合情况,并记录在 ab_map 中,ab_map 的 key 为两数和,value 为该两数和出现的次数2、遍历 C 和 D 所有元素和的组合情况,取和的负值判断其是否在 ab_map 中,若存在则取出 ab_map 对应的 value 值,count = count + value;注意C++中unordered_map会比map快得多,因为map默认按key进行排序的;class Solution {public: i.原创 2020-11-27 10:46:45 · 232 阅读 · 0 评论 -
Leetcode每日一题:164.maximum-gap(最大间距)
思路:开始没看见下面的说明,直接一sort完事了;后来看见后无疑就想到了基数排序,只有计数排序和基数排序能在最坏的情况下达到线性时间复杂度,而基数排序无疑不满足线性空间复杂度,所以这里选择基数排序;static bool cmp(int a, int b){ return a < b;}int maximumGap(vector<int> &nums){ int len = nums.size(); if (len < 2) .原创 2020-11-26 08:53:46 · 224 阅读 · 0 评论 -
Leetcode每日一题:1370.increasing-decreasing-string(上升下降字符串)
思路:规规矩矩按题目来,飘过;static bool cmp(char a, char b){ return a < b;}string sortString(string s){ int len = s.size(); if (len == 0) return ""; if (len == 1) return s; sort(s.begin(), s.end(), cmp); string res; vector<bool> flag(len, tr.原创 2020-11-25 22:02:29 · 198 阅读 · 0 评论 -
Leetcode每日一题:222.count-complete-tree-nodes(完全二叉树的节点个数)
思路:如果直接遍历二叉树的话,没有用到完全二叉树的性质,但是看懂精选题解后,就时间复杂度而言,甚至递归or遍历二叉树效率更高;//递归遍历class Solution {public: int dfs(TreeNode *root) { if(root==NULL) return -1; else return 2+dfs(root->right)+dfs(root->left); .原创 2020-11-24 09:13:36 · 238 阅读 · 0 评论 -
Leetcode每日一题:452.minimum-number-of-arrows-to-burst-balloons(最少数量的箭引爆气球)
题意:大致就是这么多区间,我要用最少的箭将这些区间全部串起来,区间是水平的,箭是垂直的;思路:对区间按照起点大小进行排序,设立max_start 和 min_end ,这样points[i+1][0]>=points[i][0],只要points[i+1][0]>=max_start && points[i+1][0]<=min_end那么,下个区间就和前面的区间有交集,就可以用同一支箭串起来,并更新max_start 和 min_end,保证一只箭能串到更多的区间;如.原创 2020-11-23 12:18:25 · 257 阅读 · 0 评论 -
Leetcode每日一题:148.sort-list(链表排序)
思路:对给定的链表进行排序,我最先想到的就是用昨天做的插入排序,一提交发现超时了,一看它这里要求时间复杂度为O(n logn)并且空间复杂度为常数级;链表的插入排序无疑复杂度为O(n2);后来使用归并排序,复杂度才达到要求;这是其中的一篇题解,我觉得写的挺详细的:链接因为递归使用栈,所以消耗了很大的内存;// 找到链表中间节点(876. 链表的中间结点)ListNode *middleNode(ListNode *head){ if (!head || !head->next.原创 2020-11-21 10:45:17 · 251 阅读 · 0 评论 -
Leetcode每日一题:147.insertion-sort-list(对链表进行插入排序)
思路:因为链表的特性,插入排序无法从当前元素往前遍历,所以这里直接从头开始查找插入位置,分头部插入、中间插入和尾部插入;ListNode *insertionSortList(ListNode *head){ if (!head || !(head->next)) return head; ListNode *cur = head->next; head->next = nullptr; ListNode *next = nullp.原创 2020-11-20 10:30:38 · 283 阅读 · 0 评论 -
Leetcode每日一题:690.employee-importance(员工的重要性)
思路:找下属,求重要性和直接用BFS即可,关键是这里的数据结构不是链表,如何最快速度找到下属是最重要的;这里我用map将每个员工的id-下标索引存储起来,直接通过id得到其员工属性;int getImportance(vector<Employee *> employees, int id){ map<int, int> m; //建立员工id-数组索引的映射; int len = employees.size(); //初始化m for (.原创 2020-11-19 09:20:11 · 223 阅读 · 0 评论 -
Leetcode每日一题:283.move-zeroes(移动零)
class Solution {public: void moveZeroes(vector<int> &nums) { int len = nums.size(); if (len < 2) return; int index = 0; for (int i = 0; i < len; i++) { if (nums[i] !=.原创 2020-11-19 08:50:33 · 210 阅读 · 0 评论 -
Leetcode每日一题:134.gas-station(加油站)
思路:就按题目所给的要求来,到一个站点,就减去消耗的油,如果没油了,返回false,否则,加上该站点加的油,重复直到开到入口点;注意到最后一个站点时,要把下一个站点设为0;int init = 0;int flag = true;void dfs(vector<int> &gas, vector<int> &cost, int len, int now, int remain) //从enter口开始{ //开到下一个点,消耗了油 rema.原创 2020-11-18 15:05:51 · 270 阅读 · 0 评论 -
Leetcode每日一题:204.count-primes(计数质数)
思路:普通的做法肯定超时,这里介绍厄拉多塞筛法,非常适用于质数的题; 比如说求20以内质数的个数,首先0,1不是质数.2是第一个质数,然后把20以内所有2的倍数划去.2后面紧跟的数即为下一个质数3,然后把3所有的倍数划去.3后面紧跟的数即为下一个质数5,再把5所有的倍数划去.以此类推.int countPrimes(int n){ vector<bool> rec(n, true); int i = 2, count = 0; //厄拉多塞筛法主体 while (i < n.原创 2020-11-17 13:04:59 · 246 阅读 · 0 评论 -
Leetcode每日一题:1030.matrix-cells-in-distance-order(距离顺序排列矩阵单元格)
static bool cmp(vector<int> a, vector<int> b){ return a[2] < b[2];}vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0){ vector<vector<int>> res(R * C, {0, 0, 0}); int index = 0; f原创 2020-11-17 12:45:16 · 164 阅读 · 0 评论 -
leetcode每日一题:406.queue-reconstruction-by-height(根据升高重建队列)
思路:先对队列进行排序,k小的排前面,如果k相等,那么按照h小的排序;随后进行插入,每次插入元素 i ,检查前面有多少人升高比i的高,并对人数计数,对于相同的k,i应该按从小到大的顺序插入;static bool cmp(vector<int> a, vector<int> b){ if (a[1] < b[1]) return true; else if (a[1] == b[1]) { return a[0] .原创 2020-11-16 13:48:59 · 235 阅读 · 0 评论 -
Leetcode每日一题:402.remove-k-digits(移掉k位数字)
思路:我们只需从左向右扫描k次,每一次都扫描到递增序列的峰值,再把它删除,最后留下的便是最小值;string removeKdigits(string num, int k){ int len = num.size(); if (len == k) return "0"; for (int i = 0; i < k; i++) { //要删除的元素下标del int del = 0; //从左向右.原创 2020-11-15 12:13:48 · 232 阅读 · 0 评论 -
Leetcode每日一题:1122.relative-sort-array(数组的相对排序)
思路:本题要求先按顺序放入arr2对应元素的前提下,再从小到大放入arr1中出现的其他元素;我们就可以先对arr1中的元素进行排序,因为只要有从小到大,肯定离不开排序,然后再优先放入arr2元素,同时把该元素置为-1,从而保证之后放入arr1其他元素时不再出现该元素,放完arr2就可以放arr1的元素了;因为最大元素和元素个数都在1000以内,所以我用的计数排序以换取更短的时间;vector<int> relativeSortArray(vector<int> &arr.原创 2020-11-14 08:57:33 · 257 阅读 · 0 评论 -
Leetcode每日一题:328.odd-even-linked-list(奇偶链表)
思路:同时分两个子链表分别向后连接属于它们的节点,遇到NULL节点时将两者连接即可;class Solution {public: ListNode *oddEvenList(ListNode *head) { if (!head || !head->next || !head->next->next) return head; ListNode *odd = head, *even = head->ne.原创 2020-11-13 08:49:13 · 247 阅读 · 0 评论 -
Leetcode每日一题:992.sort-array-by-parity-ii(按奇偶排序数组Ⅱ)
思路:法1:建立一个与原数组同大小的数组res,两次遍历A,偶数放入res的偶下标,奇数放入奇下标;法2:双指针;法3:双端队列,遍历A,计数插入前端,偶数插入尾端,然后双指针(1首1尾)对队列遍历,交换位置即可;//两次遍历class Solution {public: vector<int> sortArrayByParityII(vector<int>& A) { int n = A.size(); vector&.原创 2020-11-12 09:28:37 · 302 阅读 · 0 评论 -
Leetcode每日一题:514.freedom-trail(自由之路)
思路:首先想到的就是深度优先搜索,从ring[i]顺时针到达key[j]的路径和逆时针的路径都尝试一遍,最终肯定能得到最短路径,但肯定会超时,因为这个复杂度是幂级的,即每个点都有两种可能;所以,需要对我们尝试过的路径作标注,m["i # j"]即代表从ring[i]到key[j]的最短路径;比起动态规划还是差远了;map<string, int> m;int dfs(string ring, int x, string key, int y){ int len = ri.原创 2020-11-11 14:41:27 · 283 阅读 · 0 评论 -
Leetcode每日一题:面试题16.19.水域大小
简单的DFS//八个方位const int dx[8] = {1, -1, 0, 0, -1, -1, 1, 1};const int dy[8] = {0, 0, 1, -1, -1, 1, 1, -1};static bool cmp(int a, int b){ return a < b;}//经过(x,y)void dfs(vector<vector<int>> &land, int x, int y, int &count.原创 2020-11-09 12:26:42 · 457 阅读 · 0 评论 -
Leetcode每日一题:973.k-closest-points-to-origin(最接近原点的K个点)
思路:建立一个pair数组vec,每一个元素保存points的索引和坐标距远点的距离值,然后对vec进行排序,排序按照pair的值,最后从前到后输出k个点到返回值中即可;为什么不用map?因为不能直接对map中的元素进行排序,如果map的键放距离,值放索引,那么会存在多个索引对应一个距离值得情况,而map只会保留一个索引值,除非你用索引数组,这样就比较麻烦了;//排序函数 按值排序static bool cmp(pair<int, int> a, pair<int, int>原创 2020-11-09 09:40:37 · 216 阅读 · 0 评论 -
Leetcode每日一题:面试题 08.02. 迷路的机器人
思路:深度优先搜索;设立一个全局变量flag,一旦找到终点,便将flag置为true,防止其进一步寻求多条路径;加visited时,很多人选择new一个二维数组出来,然而这里我们只需将已被试过无法到达目标的位置设为障碍见,即grid[x][y]=1即可,节省空间和时间;int flag = false;void dfs(vector<vector<int>> &grid, int x, int y, vector<vector<int>> .原创 2020-11-08 13:50:43 · 337 阅读 · 0 评论