本文题目涉及代码均在我的Github,文件名为leetcode\题目编号
【难度】★☆☆☆☆
【代码】1\Solution.c
【难度】★☆☆☆☆
【题目分析】给定数组求求最大单向数组元素差
【题解】直接暴力
【时间复杂度】O(n2)
【代码】121\Solution.java
【优化】时间复杂度降到O(nlog2n)
【难度】★☆☆☆☆
【题目分析】求众数
【题解】用HashMap记录映射关系即可【4】
【时间复杂度】
【代码】169\Solution.java
【难度】★☆☆☆☆
【题目分析】统计给定字符集可以构造出的最长回文串长度
【题解】简单的统计计数
【代码】409\Solution.java
【难度】★★☆☆☆
【题目分析】求二叉树最长子路径
【题解】
ans=max{左子树ans,右子树ans,经过root最长路径}
经过root最长路径=左子树depth+右子树depth+分叉数
【时间复杂度】O(nlog2n)
n个节点,高度log2n
求depth时会遍历所有节点,所以求depth的复杂度O(n)
求解过程如下
f ( n ) = 2 f ( n 2 ) + O ( n ) = 2 [ 2 f ( n 4 ) + O ( n 2 ) ] + O ( n ) = 4 f ( n 4 ) + 2 O ( n ) = 8 f ( n 8 ) + 3 O ( n ) . . . = n f ( 1 ) + l o g 2 n O ( n ) = n O ( 1 ) + l o g 2 n O ( n ) = O ( n ) + l o g 2 n O ( n ) = O ( n l o g 2 n ) f(n)=2f(\frac n 2)+O(n)\\ =2[2f(\frac n 4)+O(\frac n 2)]+O(n)\\ =4f(\frac n 4)+2O(n)\\ =8f(\frac n 8)+3O(n)\\ ...\\ =nf(1)+log~2~nO(n)\\ =nO(1)+log~2~nO(n)\\ =O(n)+log~2~nO(n)\\ =O(nlog~2~n)\\ f(n)=2f(2n)+O(n)=2[2f(4n)+O(2n)]+O(n)=4f(4n)+2O(n)=8f(8n)+3O(n)...=nf(1)+log 2 nO(n)=nO(1)+log 2 nO(n)=O(n)+log 2 nO(n)=O(nlog 2 n)
【代码】543\Solution.java
【难度】★★☆☆☆
【题目分析】在一个平面上堆长宽高都为1的立方体,问最后堆成的三维体表面积,给定 g r i d grid grid数组,表示在每个格子堆积的立方体数量
【题解】在垂直方向投影很好理解,只要那个格子有堆立方体,不管堆了几个,都是上下各算一次表面积;在两个水平方向上是对称的,只用考虑一个方向上的思路,另一个同理,在某一个水平方向上的投影,每一行(列)都是独立的,所以也只要考虑单独某一行在水平方向上的表面积,一开始我没有考虑凹的情况,单纯的只考虑了最高点,实际是要考虑到每一个局部极值点,见下图:
把h1,h2…这些高度差加起来就是水平方向上的表面积
时间复杂度是 O ( n 2 ) O(n^2) O(n2)
【代码】892\Solution.java
【难度】★☆☆☆☆
【题目分析】给定2个矩形坐标,判断是否重叠
【题解】简单的计算几何,时间复杂度 O ( 1 ) O(1) O(1)
【代码】836\Solution.java
【难度】★☆☆☆☆
【题目分析】给定数组,判断能否将数组分为若干个子数组,使得每个子数组元素个数相同且元素值也相同,要求每个子数组至少有2个元素,可以只有一个子数组(即不划分)
【题解】设数组中有 k k k种不同的数字,每种数字分别有 c n t i ( i = 1 , . . . , k ) cnt_i(i=1,...,k) cnti(i=1,...,k)个,则需满足:
g c d ( c n t 1 , . . . , c n t k ) > 1 gcd(cnt_1,...,cnt_k)>1 gcd(cnt1,...,cntk)>1
n = 1 n=1 n=1时也就是 g c d ( c n t 1 ) = c n t 1 > 1 gcd(cnt_1)=cnt_1>1 gcd(cnt1)=cnt1>1
【时间复杂度】设有 n n n个元素,总共有 k k k种数,每种数字分别有 c n t i ( i = 1 , . . . , k ) cnt_i(i=1,...,k) cnti(i=1,...,k)个,那么就要求 k − 1 k-1 k−1次 g c d gcd gcd。
首先讨论一下 g c d gcd gcd的时间复杂度,考虑到 g c d ( x , y ) gcd(x,y) gcd(x,y)会生成的序列是
x , y , x % y , y % ( x % y ) , . . . x,y,x\%y,y\%(x\%y),... x,y,x%y,y%(x%y),...
设生成的序列为 { a n } \{a_n\} {an},则 a 0 = x , a 1 = y , a i = a i − 2 % a i − 1 a_0=x,a_1=y,a_i=a_{i-2}\%a_{i-1} a0=x,a1=y,ai=ai−2%ai−1
于是可以得到:
a i < a i − 1 a_i
即
a 2 ≤ y − 1 , a 3 ≤ y − 2 , . . . , a y ≤ 1 , a y + 1 ≤ 0 a_2\leq y-1,a_3\leq y-2,...,a_y\leq 1,a_{y+1}\leq 0 a2≤y−1,a3≤y−2,...,ay≤1,ay+1≤0
因此数列 { a n } \{a_n\} {an}一定是有限数列,且元素个数 n ≤ y + 2 n\leq y+2 n≤y+2,通俗的说来就是通过取模运算得到的数一定比之前的数至少要小1,所以最多经过 y y y次取模,就一定能得到最大公约数,所以 g c d gcd gcd的时间复杂度就是 O ( m a x ( x , y ) ) = O ( x + y ) O(max(x,y))=O(x+y) O(max(x,y))=O(x+y)
那么回到本题求 k k k次 g c d gcd gcd的时间复杂度就是
O ( ∑ i = 1 k c n t i ) = O ( n ) O(\sum_{i=1}^k cnt_i)=O(n) O(i=1∑kcnti)=O(n)
【代码】914\Solution.java
【难度】★☆☆☆☆
【题目分析】给定棋盘,只有白方小兵,黑方小兵,白方车(上下左右无限距离),问有几个黑方小兵在白方一步到胃的位置
【题解】模拟即可,时间复杂度 O ( n 2 ) O(n^2) O(n2)
【代码】999\Solution.java
【难度】★★☆☆☆
【题目分析】判断数组是否可划分为和相等的三部分
【题解】
首先计算一个累加和数组;
如果总和不为3的倍数直接false
将总和除3得到每部分的目标值
枚举第1部分的值,只有当它的值符合目标值时才枚举第2部分的值,如果第2部分的值也为目标值则直接true
枚举结束还没有则false
【时间复杂度】 O ( n 2 ) O(n^2) O(n2)
计算累加和复杂度 O ( n ) O(n) O(n)
枚举部分复杂度 O ( n 2 ) O(n^2) O(n2)
【代码】1013\Solution.java
【优化】最坏情况的 O ( n 2 ) O(n^2) O(n2)是当每次枚举第1部分的值都符合目标值,但是枚举第2部分的目标值都不符合,这种情况的数据就是 [ x , 0 , 0 , . . . , 0 , x , x ] [x,0,0,...,0,x,x] [x,0,0,...,0,x,x],因此如果想要继续优化,则要对连续的0作记录,比如说跳过连续的0,因为这些0并不会影响局部和;另一个思路是在枚举和时二分位置这样有望将时间复杂度降到 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
【难度】★☆☆☆☆
【题目分析】求2个字符串最长公因子串
【题解】暴力枚举这个公因子串即可,排除掉长度不能整除的
【代码】1071\Solution.java
【时间复杂度】 O ( n 2 ) O(n^2) O(n2)其中 n n n为较短字符串的长度
【优化】公因子串长度只可能是2个字符串长度的公约数,所以先计算出最小公约数,再倍增枚举会更快,另外从长往短会更快,因为短的即使匹配成功了还要试长的,但是长的如果匹配成功了就直接结束了
【难度】★☆☆☆☆
【题目分析】判断给定单词是否能被给定符号表示(每个符号只能用1次)
【题解】暴力模拟即可
【时间复杂度】单词数 n n n,单词最大长度 m m m,符号表长度 k k k, O ( n m k ) O(nmk) O(nmk)
【代码】1160\Solution.java
【优化】将符号表排序,每次匹配降到对数级别,时间复杂度可以降到 O ( n m l o g 2 k ) O(nmlog_2k) O(nmlog2k)
【难度】★☆☆☆☆
【代码】1480\Solution.c
【注C】returnSize变量无须分配内存
【难度】★★☆☆☆
【标签】搜索
【题目分析】给定01矩阵,求连通块数量
【题解】广度优先搜索或深度优先搜索均可,时间复杂度 O ( n m ) O(nm) O(nm)
【代码】200\Solution.java
【难度】★★☆☆☆
【标签】动态规划
【题目分析】求最长上升子序列长度
【题解】数组 { a n } \{a_n\} {an}, f ( i ) f(i) f(i)表示以 a i a_i ai结尾的最长上升子序列长度,状态转移方程为:
f ( i ) = max 0 ≤ j < n , a j < a i f ( j ) f(i)=\max_{0\leq j
【时间复杂度】 O ( n 2 ) O(n^2) O(n2)
【代码】300\Solution.java
【进阶】 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)算法【5】【6】
【难度】★☆☆☆☆
【标签】应用题、模拟
【题目分析】给定推特的几个基本功能模块需求,实现这些需求(发推、关注、取关、获取最近的推特)
【题解】维护一个follow关系的集合,再维护一个发推的List,各种操作都围绕这两个数据结构进行增删改查
【代码】355\Twitter.java
【难度】★★★☆☆
【标签】搜索、数论
【题目分析】给定2个容量分别为 x x x和 y y y的水壶问能否经过若干次操作后得到体积为 z z z的水
【题解】一开始想着用深搜,用布尔数组去重的话内存为炸,所以考虑用集合来进行去重;结果用了集合还是炸内存,所以考虑有更优解法,考虑这四种操作都是 x x x和 y y y的线性组合看,所以联想到裴蜀定理,即判断 z z z是否能被 g c d ( x , y ) gcd(x,y) gcd(x,y)整除,然后另外考虑一些特殊情况:
(1) x + y < z x+y
(2) x x x和 y y y中有 0 0 0
(3) z z z为0
【代码】365\Solution.java;365\Solution_Brutal.java
【优化】不过现在想来用深搜也不是不可以,可能注意剪枝之后也可以
【难度】★★☆☆☆
【标签】搜索
【题目分析】求01矩阵中在水平或垂直方向连通的最多的1的数量
【题解】深度优先搜索,原始矩阵外围添加一层0更加便利
【时间复杂度】由于每个格子最多访问1次所以就是 O ( m n ) O(mn) O(mn) m , n m,n m,n分别为矩阵长宽
【代码】695\Solution.java
【难度】★★☆☆☆
【题目分析】给定若干单词,要求按照如下方式进行压缩编码:如果一个单词是另一个单词的后缀,那么只保留那个较长的单词,单词之间用“#”连接,另外用一个数组记录每个单词在压缩后字符串中的起始位置,还原的时候就从起始位置开始一直到“#”结束,要求输出最短的压缩后字符串长度
【题解】用一个数组 q q q记录压缩后保留的单词,依次枚举每一个原始单词,如果这个单词是 q q q中某一个单词的后缀,那么就无需保留这个原始单词,如果这个单词的后缀是 q q q种某一个单词,那么就用这个单词替换 q q q中的那个单词,否则就将这个单词加入 q q q,最后统计 q q q中单词总长度,并且加上“#”的数量(也就是 q q q中的单词数量),如果有 n n n个单词,单词长度最长为 l l l,那么时间复杂度就是 O ( n 2 l ) O(n^2l) O(n2l)
【代码】820\Solution.java
【优化】如果把 q q q中弄成有序结构,是否有可能把复杂度降到 O ( n l l o g 2 n ) O(nllog_2n) O(nllog2n)呢?
【难度】★☆☆☆☆
【标签】排序
【题目分析】给定数组按升序排序
【题解】直接用sort函数即可,不过这题的本意应该是自己手写排序函数,不然也不会放在中等里了,有机会再补一下各种版本的手写排序版本吧
【代码】912\Solution.java
【难度】★★☆☆☆
【标签】模拟
【题目分析】给定一个向量 a a a,求一个向量 b b b使得这两个向量之和的各分量均不相同,即 c = a + b , c i c=a+b,c_i c=a+b,ci互不相同,要求输出 ∑ b i \sum b_i ∑bi
【题解】时间复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
首先排序,时间复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
接着从最小的开始遍历,设 p r e n u m prenum prenum=为上一个值, n o w n u m nownum nownum表示当前值, p l a t n u m platnum platnum表示目前还不能保证唯一的数的个数, h e i g h t height height表示当前值和前一个值之间的差, a n s ans ans记录累加的和,则按照如下公式更新:
p l a t n u m = { p l a t n u m + 1 , h e i g h t = 0 p l a t n u m − h e i g h t − 1 , 0 < h e i g h t < p l a t n u m 0 , h e i g h t ≥ p l a t n u m platnum= \left\{ \begin{aligned} &platnum+1&,height=0\\ &platnum-height-1&,0
a n s = { a n s , h e i g h t = 0 a n s + ( h e i g h t − 1 ) ⋅ h e i g h t 2 + ( p l a t n u m − h e i g h t − 1 ) ⋅ h e i g h t , 0 < h e i g h t < p l a t n u m a n s + ( 1 + p l a t n u m ) ⋅ p l a t n u m 2 , h e i g h t ≥ p l a t n u m ans= \left\{ \begin{aligned} &ans&,height=0\\ &ans+\frac {(height-1)\cdot height} 2+(platnum-height-1)\cdot height&,0
上述公式的解释是这样的,当前后值没有落差时,则继续积累“无家可归者”;当前后落差非常大时(超过“无家可归者”数量),则所有当前“无家可归者”都有地方住了,更新一下计数;当前后有落差但是不够大时(不够所有“无家可归者”数量),那么先安置能够安置的,然后剩下的要把数字提升到当前的 n o w n u m nownum nownum,也就是统一升高 h e i g h t height height,等待下一次产生落差时再一起分配,如果已经是最后一个数字了,那么就一次性把所有待分配位置的“无家可归者”给安排了。
【代码】945\Solution.java
【难度】★★★☆☆
【标签】搜索
【题目分析】给定一张包含0和1的二维地图,其中0和1分别代表海洋和陆地,要求输出最远的海陆距离,这里的距离是曼哈顿距离,即求:
max ( i 1 , j 1 ) = 0 { min ( i 2 , j 2 ) = 1 ∣ i 1 − i 2 ∣ + ∣ j 1 − j 2 ∣ } \max_{(i_1,j_1)=0}\{\min_{(i_2,j_2)=1}|i_1-i_2|+|j_1-j_2|\} (i1,j1)=0max{(i2,j2)=1min∣i1−i2∣+∣j1−j2∣}
【题解】地图规模是 100 × 100 100\times100 100×100,也就是有 1 0 4 10^4 104个点,最容易想到的思路就是暴力,每两个点计算一下距离,这样的复杂度就是 O ( 1 0 8 ) O(10^8) O(108),设地图的边长为 n n n,即时间复杂度为 O ( n 4 ) O(n^4) O(n4),写了一下超时了;实际上还有一个广搜的思路,可以把时间复杂度降到 O ( n 2 ) O(n^2) O(n2),也就是从陆地出发(海陆距离为0),将所有陆地放到队列里,然后再一个个出队,每个点出队就把它周围的4个点入队(海陆距离+1),当然如果有的点之前已经入队过了就不用再入队了,每个点都只会入队一次并出队一次,最后那个入队的点的海路距离就是题目所求的海陆距离,总共有 n 2 n^2 n2个点,所以时间复杂度就是 O ( n 2 ) O(n^2) O(n2)
【代码】
1162\Solution_brutal.java
1162\Solution.java
【题目分析】一张人名信息表,一张住址表,要输出人名及其对应的住址,即使没有住址也要输出人名
【题解】left join【7】
【代码】175\Solution.sql
【题目分析】给定员工信息表,包含员工ID,姓名,工资,和上级ID,如果这个员工本身就是上级,那么上级ID就是null,要求出工资比上级大的员工姓名,最后输出的属性名要设置为Employee
【题解】将表与自身进行join连接
【代码】181\Solution.sql
【题目分析】一张表只有2个属性(其中1个是id),要求输出其中重复的条目
【题解】使用group by having 和count()聚合函数
【代码】182\Solution.sql
【思考】1.where为什么不能用聚合函数2.where group by having的顺序为什么是这样的3.执行group by然后having的内部细节是怎样的
【题目分析】给定2张表,1张是客户名单,另一张是订单记录,要求输出所有没有下过订单的客户名字
【题解】提供3种解法,Solution1是在where子句中用not in判断客户id有没有在订单记录中,Solution2是将客户名单left join订单记录,然后输出这样操作后右边is null的客户,虽然Solution2通过了leetcode的测试,但是我觉得其实还是有问题的,因为这样输出可能会有重复的客户,所以Solution3就是在Solution2的基础上加了一个去重distinct,不过需要注意的是,这里distinct的不是Name,而是(Name,Id)元组,因为有可能存在重名的人,有趣的是,Solution3的执行时间是最快的,这其中的原理还没有深究
【代码】183\Solution1.java;183\Solution2.java;183\Solution3.java
【思考】为什么Solution3在Solution2的基础上加上distinct的去重操作之后反而更快了?
【题目分析】给定一张表,表中有id和对应的邮箱,要求删除重复的邮箱,对于重复的邮箱只保留id最小的那行记录,要求必须使用delete语句
【题解】按照每个邮箱分组,得到min(id)子表,然后将原表中id不在这个min(id)子表中的记录都delete掉,需要注意的是如果直接写delete from 表A where 属性名 not in(select 属性名 from 表A…)这样会报错,必须要将子表的结果再select一遍才行,这是mysql特有的问题,像oracle就不用再select一遍【9】
【代码】196\Solution.sql
【题目分析】给定天气表,包含id,日期,温度,要求输出所有升温日期(比前一天温度要高)对应的id
【题解】自己join自己;DATE_ADD函数
【代码】197\Solution.sql
【题目分析】一张表包含国名、人口、面积,要求找到其中人口超过一定规模或面积达到一定规模的国家
【题解】where子句
【代码】595\Solution.sql
【题目分析】给定包含电影编号、名字、描述、得分的表,要求输出奇数编号,描述不无聊的电影,按照得分从高到低排序
【题解】字符串要加引号;order by desc
【代码】620\Solution.sql
【题目分析】要求把表格中的性别男女互换,要求只能用一个update,不能用select
【题解】使用if或者case when
【代码】
627\Solution_case.sql
627\Solution_if.sql
【题目】A,B,C三个线程先后启动调用打印语句,要求最终的打印序列一定是"firstsecondthird"
【题解】想到设一个变量初始为0,然后只有打印完"first"后才加1,然后打印"second"的语句一定要等到它为1时才执行,"third"同理,不过只用普通的int是不行的,甚至volatile也不行,必须要用AtomicInteger才行【10】
【代码】leetcode\1114
【难度】★☆☆☆☆
【题目分析】对给定字符串进行压缩,压缩方法为将重复的字符用数字表示
【题解】模拟即可
【时间复杂度】 O ( l e n ) O(len) O(len)
【代码】01.06\Solution.java
【难度】★★☆☆☆
【题目分析】给定 n u m s nums nums数组,求最大的不连续子数组和
【题解】动态规划,时间复杂度 O ( n ) O(n) O(n)
状态转移方程, f ( i ) f(i) f(i)表示以 n u m s [ i ] nums[i] nums[i]结尾的最大不连续子数组和:
f ( i ) = { n u m s [ 0 ] , i = 0 n u m s [ 1 ] , i = 1 n u m s [ 0 ] + n u m s [ 1 ] , i = 2 m a x ( f ( i − 2 ) , f ( i − 3 ) ) + n u m s [ i ] , i ≥ 3 f(i)= \left\{ \begin{aligned} nums[0],i=0\\ nums[1],i=1\\ nums[0]+nums[1],i=2\\ max(f(i-2),f(i-3))+nums[i],i\geq 3\\ \end{aligned} \right. f(i)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧nums[0],i=0nums[1],i=1nums[0]+nums[1],i=2max(f(i−2),f(i−3))+nums[i],i≥3
【代码】17.16\Solution.java
【难度】★☆☆☆☆
【题目分析】找出给定数组中最小的k个数
【题解】排序后输出即可
【代码】OFFER.40\Solution.java
【难度】★☆☆☆☆
【题目分析】约瑟夫问题,输出最后的剩的数字
【题解】暴力模拟即可
【代码】OFFER.62\Solution.java
【优化】约瑟夫问题数学解【8】
【1】Latex参考文档
【2】在线latex工具
【3】Cmd Markdown 公式指导手册
【4】【简易版】HashMap(增删改查)
【5】最长上升子序列o(nlogn)复杂度一种简单易懂的理解
【6】最长递增子序列
【7】SQL的各种连接Join详解
【8】约瑟夫问题的三种解法
【9】You can’t specify target table ‘表名’ for update in FROM clause错误
【10】按序打印