LeetCode
记录一些刷leetcode过程中,总结的一些知识点或易错点;
Jiu_R
coder
展开
-
剑指Offer60.n个骰子的点数
题目:剑指Offer60.n个骰子的点数输入n个骰子,则每次丢n个骰子,可能出现的点数和为[ n,6n ];按点数和从大到小的顺序,输出出现该点数的概率;思路:原创 2021-08-02 14:58:15 · 96 阅读 · 0 评论 -
O(1)求前n个正整数的亦或值
找出规律: int totalxXor; switch (n % 4) {//求前n个正整数的亦或值 case 1: totalxXor = 1; break; case 2: totalxXor = n + 1; break; case 3: totalxXor = 0; break; default: totalxXor = n; break; }...原创 2021-05-11 16:24:32 · 91 阅读 · 0 评论 -
7.整数翻转
题目:7.整数翻转把一个int值翻转输出,若翻转后溢出int,就返回0;不能使用64位整数;思路:本题麻烦在溢出如何处理;本题不能使用64位整数,因此不能用long,只能在int上下功夫;1.溢出前检查:时间O(log10 x):循环x的位数次,空间O(1)通常对一个数组转化成数字,res = res * 10 + nums[ i ]是从高位往低位遍历;本题要把整数翻转,例如1234,刚好把4理解成高位,就可以按上式计算倒过来的值,这样好的一点是,像123000这样的数,不用额外..原创 2021-03-19 00:08:49 · 159 阅读 · 0 评论 -
面试题34.二叉树中和为某一值的路径
剑指Offer34.二叉树中和为某一值的路径题目:从根root到叶子节点为一条路径;返回树root中路径和为sum的路径;思路:路径肯定是从根开始,因此必须是前序遍历;1.回溯:O(n),O(n)class Solution {private: vector<vector<int>> res; vector<int> path; void backtracking(TreeNode* cur, int remain) { .原创 2021-02-22 22:17:31 · 68 阅读 · 0 评论 -
338.比特位计数
338.比特位计数题目:输入一个num,输出一个长度为n+1的数组,元素分别为[ 0,num ]对应的二进制数的1的个数;思路:1.暴力:时间O(32n),空间O(1)遍历[ 0,num ],分别计算每个数的二进制的1的个数;class Solution {public: vector<int> countBits(int num) { vector<int> res(num + 1); for (int i = 0; i &.原创 2021-03-03 11:26:32 · 122 阅读 · 0 评论 -
96.不同的二叉搜索树
96.不同的二叉搜索树题目:1~n共n个数作为二叉搜索树的节点值,计算这n个数能构成多少种二叉搜索树(BST)?思路:二叉搜索树要求左子树节点值 < 跟节点值 < 右子树节点值;例如以 i 为根节点值,则 i 的左子树数目 * i 的右子树数目就是以 i 为根节点的二叉搜索树的数目;1~n的数组要构成二叉搜索树,即枚举1 ~ n每个值都作为根节点,再求和即可;1.DP:O(n^2),O(n):需要一个大小为n+1的dp数组①dp数组下标和含义:dp[ i ] ..原创 2021-02-17 21:18:37 · 107 阅读 · 0 评论 -
561.整数拆分Ⅰ
561.整数拆分Ⅰ题目:一个长度为2n的整数数组nums,将其两两分成n组;求n个组的min(每组中的两个数)和最大为多少;思路:既然要两两分组,且求和时只计算其中小的那个,那么最小的搭配次小的,才能不浪费,例如1,2对比1,5的结果都是1,第二种情况的5比2造成更大浪费,因为这个5有可能在其他组会作为那个小的数被累加到结果中去;1.排序:O(nlogn):主要是sort的时间复杂度,O(logn):排序所需的栈空间先从小到大排序,则分组情况就是按从小到大两两分组,因此累计每组中的..原创 2021-02-16 11:42:52 · 87 阅读 · 1 评论 -
63.不同路径Ⅱ
题目:63.不同路径Ⅱ思路:与62题62.不同路径的区别:矩阵中的某些格子有障碍,代表不能到达,应该把dp [ i ] [ j ] = 0即可;那么,就无法使用组合数了;若使用DP,无法有华为一维数组dp,因为有障碍,初始化都不同,而使用一维数组时,默认第一行第一列都为1,因此dp[ i ] += dp[ i - 1 ]时,若逐行算,当第一列中有障碍时,有的行的第一列应该+=0,有的应该+=1,会出现不一致的情形,因此无法作此优化;1.DP:O(mn),O(mn)class Solution.原创 2021-02-15 11:23:32 · 75 阅读 · 0 评论 -
62.不同路径
62.不同路径题目:从一个m*n的矩阵的左上角[0,0]走到右下角[m-1,n-1]有几条路径?思路:1.DFS:O(2^(m+n-1)):大概算一下,矩阵中几乎每个位置都是由上或左两个方向到达,从而进行一次递归,因此总的递归次数肯定是2的指数次,指数差不多为矩阵总格子数,造成超时;空间主要为递归时栈的开销;class Solution {private: //相当于一棵二叉树 int dfs(int i, int j, int m, int n) { ..原创 2021-02-14 13:38:44 · 103 阅读 · 0 评论 -
746.使用最小花费爬楼梯
746.使用最小花费爬楼梯题目:数组cost的每个元素cost[ i ] 表示在 i 台阶处需花费cost [ i ] 体力值才能向上走;每次花费了体力可以选择向上走一或两步;初始位置为下标为0或1处;求最少花费多少体力值可以到达楼顶(楼顶指cost.size( ) 处)思路:1.DPdp数组下标及class Solution {public: int minCostClimbingStairs(vector<int>& cost) { ..原创 2021-01-30 17:24:05 · 121 阅读 · 0 评论 -
122.买卖股票的最佳时机Ⅱ
122.买卖股票的最佳时机Ⅱ题目:一个数组prices的每个元素prices[ i ] 表示一支特定股票当天的价格;不能同时持有多只股票,只能卖出去才能再买;求最高利润;思路:股票系列问题是典型的DP问题;但本题还可以用贪心,更简单;1.DP:O(n),O(1)维护两个变量:持有股票的最多钱 和 不持有股票的最多钱class Solution {public: int maxProfit(vector<int>& prices) { ..原创 2021-01-28 19:01:27 · 138 阅读 · 0 评论 -
376.摆动序列
376.摆动序列题目:摆动序列:一个序列的连续两个元素这段增加,下一段减少,不能出现连续增/减的情形;一个数组nums的值有正有负;找出nums的最长摆动序列的长度;思路:更高才更容易碰到低的,更低才容易碰到高的,因此相当于只统计波峰和波谷的个数,忽略掉中间坡上的数;//统计波峰波谷数目class Solution {public: int wiggleMaxLength(vector<int>& nums) { int n = ..原创 2021-01-28 16:33:33 · 76 阅读 · 0 评论 -
968.监控二叉树
968.监控二叉树题目:一棵树所有节点值为0;选择适当结点装摄像头,摄像头可以监控本身结点以及上下父子两层;返回用最少的摄像头监控整棵树;思路:由于一个结点装摄像头可以覆盖三层,因此要想用最少的摄像头覆盖,就要尽可能每个摄像头都覆盖三层,尽量不要浪费;对于树,无非就是前中后层序遍历;由于树类似一个三角形,选择从下往上遍历,优先在下层装,可以最大程度覆盖结点,从下往上对应后序遍历;每个节点状态只有三种,分别用0,1,2表示:0:未覆盖 1:装摄像头 2:没装摄像头但被覆盖用递归..原创 2021-01-28 10:37:03 · 93 阅读 · 0 评论 -
714.买卖股票的最佳时机含手续费
714.买卖股票的最佳时机含手续费题目:数组prices的每个元素prices [ i ]代表每天的价格,选择买入卖出时机,返回最多赚的钱;思路:1.贪心:O(n),O(1)本题用贪心解决的话,关注点并不在具体的买入和卖出日期上,而是将利润分解开计算的,但分解开的这些操作与实际操作其实也是有一定对应关系的;minPrice并不一定是真正实际操作时的买入价格:实际一笔交易的利润,在计算时可能会被分解开,minPrice充当每一次计算利润时的买入价格;每次计算利润时,都会扣手续费。若一..原创 2021-01-27 15:37:54 · 77 阅读 · 0 评论 -
交换两变量值的方法
引自版主:引入第三变量作为中间值优点:适用于任何类型;缺点:需要额外引入第三变量不引入第三变量加减法缺点:只能处理整型,且可能有溢出的风险位异或转换为二进制的位运算,因此不会溢出,但只能无法处理不能转成二进制的类型指针(交换大type的变量,效率仍然高)实际没有交换两变量的内存,而只是修改了两指针的地址栈利用栈的先入后出的特性,在出栈时对两变量重新赋值...原创 2020-11-30 12:58:42 · 142 阅读 · 0 评论 -
二叉树的下一个结点
二叉树的下一个结点题目:返回中序遍历下给点结点pNode的后继;思路:中序遍历是:左 中 右 ,因此按pNode是否有右子树分类判断;/*struct TreeLinkNode { int val; struct TreeLinkNode *left; //左孩子 struct TreeLinkNode *right; //右孩子 struct TreeLinkNode *next; //父亲 TreeLinkNode(int x) :val(x).原创 2021-01-26 16:18:36 · 63 阅读 · 0 评论 -
738.单调递增的数字
738.单调递增的数字题目:给一个非负整数N,返回一个<=N的最大整数,其从高到低的每位数递增;思路:1.贪心 O(n):n为数字长度 ,O(n) :需要一个数字长度大小的字符串,便于操作若使用暴力解法,判断N不行就判断N-1,会超时,因此需设法少判断一些数字;整数N转换为字符串便于操作;nums[ i ] > num[ i - 1 ],则num[ i - 1 ] --,num[ i ] = ‘9’,例如N=85应返回79;只能从后往前遍历:①对N的减小最弱,才能找到..原创 2021-01-26 10:55:49 · 97 阅读 · 0 评论 -
435.无重叠区间
435.无重叠区间题目:一个vector<vector>intervals ,每个元素intervals[ i ] = [ intervals[ i ] [ 0 ],intervals[ i ] [ 1 ] ] 代表一个区间;可以调整元素顺序,求最少删掉几个区间使得剩余区间不重叠;区间相切不算重叠;思路:依然是先排序:按区间的左边界排序从左到右遍历,从最小右边界考虑哪些需要删,哪些需要留//直接统计需要删除的class Solution {public: ..原创 2021-01-25 10:09:32 · 58 阅读 · 1 评论 -
56.合并区间
56.合并区间题目:vector<vector> intervals的每一个元素intervals[ i ] : intervals[ i ] [ 0] , intervals[ i ] [ 1 ]表示一个区间范围;把有重复部分的区间合并成一个大区间,并返回合并后的vector<vector>;思路:先排序,规则是:按区间起点从小到大排序,起点相同的区间,按终点从小到大排序;从前往后遍历,若有重叠,就合并;若没重叠,说明不能合并,就把前面已经合并的部分添加进结..原创 2021-01-23 11:08:01 · 66 阅读 · 0 评论 -
763.划分字母区间
763.划分字母区间题目:字符串S由小写字母组成;把S分割成尽可能多的段;保证同一字母最多只会在一个段内出现;返回每一段区间长度的列表;思路:想要把同一字母圈在一个区间内,就需要找到每一个字母出现的右边界;在从前往后遍历的过程中,如果成功到达前面已经遍历过的所有字母的最远右边界,说明前面这些字母最远也就到这,因此不用担心后面会再出现前面这些字母,也就实现了把前面这些种类的字母圈在了一个区间;再接着寻找下一区间,直至遍历结束;class Solution {public:..原创 2021-01-23 10:32:33 · 115 阅读 · 0 评论 -
452.用最少数量的箭引爆气球
452.用最少数量的箭引爆气球题目:points[i]表示一只气球,[ points[i][0],points[i][1] ]表示气球的范围;思路:class Solution {public: int findMinArrowShots(vector<vector<int>>& points) { int n = points.size(); if (n <= 1) return n; ..原创 2021-01-21 10:22:14 · 71 阅读 · 0 评论 -
35.搜索插入位置
35.搜索插入位置排序数组nums中寻找目标值target,若存在target则返回下标,不存在就返回插入位置;思路:二分不能套模板,关键在于维护不变量,选择了一种表示方法,各种判断条件,区间更新,返回值等等都要与之配套;1.左闭右闭区间[ l ,r ]class Solution {public: int searchInsert(vector<int>& nums, int target) { int l = 0, r = nums..原创 2021-01-20 10:36:15 · 68 阅读 · 0 评论 -
628.三个数的最大乘积
628.三个数的最大乘积题目:从数组nums中找出乘积最大的三个数;nums[i]∈[ -1000, 1000 ],nums.size() ∈ [ 3, 10000 ];乘积不会溢出;思路:最大的情况一定是 最大的三个数 或 最小的两个数*最大的那个数;那就需要找出这两种情况1.排序class Solution {public: int maximumProduct(vector<int>& nums) { sort(nums.begin(.原创 2021-01-20 09:39:34 · 79 阅读 · 0 评论 -
406.根据身高重建队列
406.根据身高重建队列思路:数组vector<vector>people的每一个元素people[i] = [ h[i], k[i] ],h[i]表示他的身高,k[i]表示他前面有几个身高>=他的;数组people是打乱顺序的,要根据people的每个人的情况,调整people的元素顺序,恢复出原队列;1.贪心:每个人的身高h[i]是确定的,但k[i]只知道他前面有几个身高>=他的,但并不知道具体是哪些人;要对people调整元素顺序,可依靠的就是h和k,因此设法先.原创 2021-01-17 14:28:24 · 90 阅读 · 0 评论 -
1018.可被5整除的二进制前缀
1018.可被5整除的二进制前缀思路:在一个二进制数组A中,判断子串[ 0,i ]表示的二进制数是否被5整除,返回一个vector1.顺序读取,依次判断:O(n) ;O(n) ;类似于读取十进制,sum = sum * 10 + nums[ i ] ;求出每一个子串的十进制数并判断是否被5整除class Solution {public: vector<bool> prefixesDivBy5(vector<int>& A) { vec.原创 2021-01-14 19:37:41 · 359 阅读 · 0 评论 -
860.柠檬水找零
860.柠檬水找零思路:数组bills表示每笔交易顾客给的钱,由5,10,20三种情形,但每杯水固定5块,因此需要找钱;若能顺利找钱,一直处理完数组bills,return true,否则return false;模拟按顺序处理数组即可,分别处理5,10,20的情形;对于20的找零,运用贪心优先找10+5,其次再找5+5+5,因为5更万能,10只能用来找20的,找钱时20完全用不上,因此只需维护5和10的数量;class Solution {public: bool lemo.原创 2021-01-11 10:24:03 · 61 阅读 · 0 评论 -
135.分发糖果
135.分发糖果思路:一个表示孩子们得分的数组ratings;每个人至少分一个糖;相邻孩子中,分高的孩子糖得到更多糖,求所需糖的最少个数;贪心:首先每个孩子至少一个糖;对于相邻孩子来说,我如果比左边分高,我的糖也要比他多;我如果分比右边分高,我的糖也要比他多;因此这件事分为左右来看待;先只考虑左边:局部最优: 从前往后遍历,当我比左手边孩子分高时,糖比他多一个; 全局最优:整个数组中,所有分比左手边孩子分高的人,糖也比他多一个;再考虑右边,同时不能破坏左边:局部最优:从后往前遍历,当.原创 2021-01-08 15:40:14 · 71 阅读 · 0 评论 -
134.加油站
134.加油站思路:两个非空的长度相等的数组gas和cost,分别代表在每个位置可以获得的油量以及到下一个地方需耗费的油量;车的起始油量为0,找出可以安全走完一圈的起始点;结果如果存在必唯一,就返回起始点下标,否则返回-1;暴力:O(n^2):两层循环;O(n):外层循环长度为n,每层需要O(1)内存;分别尝试以每一个位置为起始点,看是否能绕完一圈;class Solution {public: int canCompleteCircuit(vector<int&g.原创 2021-01-07 09:45:28 · 119 阅读 · 0 评论 -
x的n次的时间复杂度
求x的n次方思路:比较容易想到的是一层循环,不断更新res;//O(n)int function1(int x, int n) { int res = 1; for (int i = 0; i < n; ++i) { res *= x; } return res;}可以用递归,但复杂度仍为O(n)//O(n) = 递归深度:n * 单层递归时间复杂度:O(1)int function1(int x, int n) { if (n.原创 2021-01-06 19:02:26 · 2974 阅读 · 0 评论 -
lc超时时间
我的电脑CPU是2.7GHZ,即27亿HZ,f = 1 / T, 代表计算机1s可以进行27亿次操作。但这27亿包括一条指令需要不止一次操作 + 计算机内存管理往往使用缓存技术,由于运行局部性,导致频繁访问相同地址的时间比访问不同地址要快一些 + 不同进程抢占资源。lc上通常超时时间是1s,实际用到leetcode上代码运行的操作是:1s大概5亿次;即当程序时间复杂度是O(n)时,程序运行所需的实际操作次数超过5亿次就会超时,同理,O(n^2)不超时的操作次数是根号下5亿次;//测试代码#includ原创 2021-01-06 17:37:54 · 655 阅读 · 0 评论 -
1005.k次取反后最大化的数组和
1005.k次取反后最大化的数组和思路:数组元素都是整数(可能有正有负);单次操作是对某元素取反,这样的操作共k次(可对某元素重复操作);执行k次操作后,数组元素最大的和;贪心:如果数组有负元素的话,自然优先把负变为正,且最优先的是最小负值(即绝对值最大的元素);如果数组所有元素都为正了,K仍没用完,就全用在尾元素上:为了最大限度的减小损失,应该优先把最小正值变为负,同样如果变了一次之后尾元素变为负,如果K还没用完那自然应该把尾元素变回正,因此应该把剩余的K全用在尾元素上;class.原创 2021-01-06 08:56:52 · 198 阅读 · 1 评论 -
55.跳跃游戏
55.跳跃游戏思路:一个非负整数数组nums, nums[i]表示i位置最多可以走几步(但具体一步一步走,还是一下走Nums[i]步并不关心);目标是判断是否能走到数组最后一个元素的位置;贪心:不要去考虑具体怎么走,只考虑在某个位置上的最大步数,看当前位置最远能够到哪;而在当前位置能够到的范围内,去看每个位置是否能接着延长这个最远位置;循环条件i<=cover,cover是一个可变的值;在当前的cover内,不断去延申cover,如果能覆盖到nums.size()-1就算成功。反之.原创 2021-01-05 10:24:25 · 113 阅读 · 0 评论 -
122.买股票的最佳时机Ⅱ
122.买股票的最佳时机Ⅱ思路:一个数组,prices[i]表示该股票第i天的价格;手里只能拿一只股票,想要再买只能先把手上的卖出去才能买;不限制进行多少次交易;贪心:O(N); O(1);一笔第i天买,第j天卖的交易的利润,可以分解为从这段时间内每天都进行一次交易的最终和;保证每天都赚最多,最终就赚的最多;class Solution {public: int maxProfit(vector<int>& prices) { int r.原创 2021-01-05 09:53:56 · 74 阅读 · 0 评论 -
53.最大子序和
思路://遍历一次:O(n),class Solution {public: int maxSubArray(vector<int>& nums) { int res = INT_MIN, cur = 0; for (int i = 0; i < nums.size(); ++i) { cur += nums[i]; if (cur > res) res = cur; //出现..原创 2020-12-31 11:32:21 · 46 阅读 · 0 评论 -
455.分发饼干
455.分发饼干思路:要把一堆饼干分给一群小孩,且每个小孩最多拿一块;要点:既然小孩最多拿一块,也就不存在一块饼干掰开或者几块小饼干给一个胃口大的人这些情况了;要求的是能拿到饼干的最多人数,即胃口大小都一样,只算作一人;所以我们以饼干为基准,以不浪费饼干为原则,尽可能把每一块饼干都找到主人;流程:首先把小孩和饼干都排序;① 优先分小饼干,从胃口最小的孩子还是找,努力用这块饼干满足一个胃口尽可能小的人(若这块饼干给了一个胃口大的人,那么就一定需要另一块更大的饼干去满足小胃口的人但并不一定.原创 2020-12-31 09:52:50 · 67 阅读 · 0 评论 -
51.N皇后
51.N皇后思路:在一个nn的方针上放n个皇后棋子,保证每个皇后独占一行,一列,两条斜线,因此需要isValid这个判断函数;放置皇后时,从第0行逐行往下找,这对应树的深度;对于每一行有n列,遍历每一列,并尝试在每一个位置放置皇后,横向遍历对应树的宽度;终止条件:成功走到第n行;循环:对当前curRow行的每一列都尝试,且仅有该位置有效时才递归去寻找下一层;棋盘初始为nn的’.’,方便放皇后时的操作;class Solution {private: vector<vecto.原创 2020-12-28 17:12:39 · 130 阅读 · 0 评论 -
322.重新安排行程
322.重新安排行程思路:vector<vector>& tickets;tickets的元素是一对出发机场和目的机场,我们目的是找一条起点为"JFK"的路径把它们串起来;运用回溯,每选一趟航班并把它添加到path中,然后从可选集合中去掉它,直到把所有航班都去掉(不去掉的话可能会死循环);终止条件:path包含了所有站点;循环:由于同一个出发机场可能对应多个到达机场,且题目要求如果最终找到不止一条合理路径path,应选择最小的那个。这里为了表示一个出发机场映射多个到达机..原创 2020-12-28 16:05:42 · 75 阅读 · 0 评论 -
491.递增子序列
491.递增子序列思路:不能修改原数组,因此重复元素不一定相邻;同一层中可选的值必须是当前层中首次出现(因此需要用unordered_set记录当前层使用过的值,注意到本题的值区间尾[-100,100]),因此可以优化为长度为201的layer数组,将值+100映射到layer数组上;递增子列长度至少为2;递增:要选的值>=path的尾元素(注意选择首个元素时path为空,可以直接加入path)class Solution {private: vector<vec.原创 2020-12-11 10:21:18 · 134 阅读 · 1 评论 -
46.全排列
46.全排列思路:全排列的话,当前结点值的候选区间是:从根到当前结点这条路径中未使用过的,因此需要使用used数组将这条路径使用过的值作个标记。自然当前结点值的选择就是从0开始,所有未被标记过的都可以,如果作出了一个选择,就把这个增添到路径used中,下一层递归中就不会被重复选到了。并且对于同一层的后面结点,需要恢复现场,把选过的那个恢复为false,这样就不会影响后面结点的孩子了class Solution {private: vector<vector<int>&g.原创 2020-12-11 09:59:03 · 90 阅读 · 0 评论 -
哈希表
C++中的几种哈希表,有序对应底层实现是红黑树,无序对应底层实现是哈希表(之所以几种有序容器使用红黑树,但也称为哈希表,是因为他们也使用hashfunction将key映射为index,只是底层的符号表使用红黑树来存储;)当key范围有限且分布密集(如全是字母),优先使用数组;若key范围没有限制或分布特别分散,则使用set系列;若不仅需要key还需要保存value,则使用map系列;同一个数组内的两数之和:哈希表同一个数组内的三数之和:第一个数用最外层for,内部用双指针判断后两个数同一个数组内.原创 2020-12-08 15:46:09 · 196 阅读 · 0 评论