Leetcode 解题报告

来源:互联网 发布:单片机uart是什么意思 编辑:程序博客网 时间:2024/05/01 12:00


据说刷完leetcode是准备编程面试的第一步。想到明年可能就要开始找工作了,先准备着吧。

计划今年11月份前做完,大概平均每天2-3题,难度应该不大,贵在坚持!
代码放在github上,地址:https://github.com/xingjian-f/Leetcode-solution

(10.1 更新,从6.30开始,截止到10.1,三个月时间,目前做题情况 solved 256/ 390 problems. 做完了所有未加锁的初等、中等和部分hard题目。还有一个月时间,做完剩下的hard题目,加油!

简略解题报告

1 Two Sum
三种解法:
1 暴力枚举所有的两两组合,检查它们的和是否等于目标,复杂度O(n^2)
2 建字典,用一个列表记录每个数字在哪些位置出现过(因为一个数字可能出现多次),然后重新扫描一遍所有输入数字,检查目标和它所对应的差值是否在字典中出现过,以及它们的位置是否重叠。根据建字典的方法,复杂度会有不同。哈希实现,O(n), 树实现,O(nlogn)。
3 不用建字典,先对输入数组排序,然后用二分搜索去查找。复杂度O(nlogn)

2 Add Two Numbers
整数加法,但数字是用链表表示的。可以模拟加法,这个方法一定要注意5+5=10这种多生成了一位的情况,很容易忽略(我就wa了一次),或者先把两个数从链表解释出来,然后做加法,再解释回链表的表示,问题是要注意这个可能需要大整数加法,那又回到了模拟加法的问题,不过python这种内置大整数加法的语言就不用考虑这个问题了。

3  Longest Substring Without Repeating Characters
two pointers 方法,O(n)解决。需要字典记录当前子串每个字符出现的位置,根据字典的实现方法不同,也可能O(nlogn)。

4  Median of Two Sorted Arrays
复杂度要求O(log(m+n)), 不过我觉得最快也就是O(2*logm*logn),类似求第K大数。实现写的是O(n+m)的合并操作,然后在有序数组上求中位数,也可以过。

5 Longest Palindromic Substring
用dp[i][j]表示(i-j)这一子串是否为回文串,复杂度O(n^2),按理说1000长度的数据是可以过的,但是python实在太慢,用这种方法会超时。
需要优化。若dp[i]表示,以i结尾的最长子串长度,maxl表示目前已知的最长长度。因为只有当dp[i]大于maxl时,才有求得必要,所以只考虑dp[i]大于maxl的情况,只有如下两种:
1 (i-maxl~i) 是回文串 , dp[i] = maxl+1
2 (i-maxl-1~i) 是回文串, dp[i] = maxl+2
dp[i]不可能有更大的情况,因为有的话,dp[i-1] 一定大于maxl。
这个优化,可以使枚举情况数大大较少, 复杂度依然是O(n^2)。实际代码中dp可以不用记录。

6. ZigZag Conversion
可以直接模拟,也可以找数学表达式,我选择了第二种自己相对弱的方式。
n表示一共有多少行,i表示现在计算的第i行,k表示枚举到第几个“峰”。那么同一行中每一个峰,左右两边各对应一个数字,它们的表达式分别为
-i + (2*n-2) * k 和 i + (2*n-2*k) ,然后注意判断边界。另外注意!当n==1时,这个公式不成立,直接返回输入的字符串即可。

7. Reverse Integer
Leetcode上题目的特点就是坑多,一定要想清楚测试用例,确保程序考虑周全。负数和0都很容易想到,但是题目还要求考虑整数反转后数值太大溢出的问题,但python是没有这个问题的,直接转str,反转,再转int就可以了,不过题目要求超出32位整数范围输出0。

8. String to Integer (atoi)
按照题目要求做就好了,真正面试的时候,关键部分应该在于主动问出所有可能的输入情况以及相应要求的应对措施。

9. Palindrome Number
注意负数不是回文数,面试要自己问。

10. Regular Expression Matching
要求s和模式串p完全匹配,所以用p贪心去匹配s是不行的,因为有可能p有的部分s不能满足。可以先考虑回溯法,计算s[i:]和p[j:]能否匹配,找到可行策略后,加个dp数组变成记忆化搜索高效求解。
如果p[j+1]=='*':
dp[i][j] = dp[i][j+2] or (match(s[i],p[j]) and (dp[i+1][j+2] or dp[i+1][j]))
else:
dp[i][j] = match(s[i],p[j]) and dp[i+1][j+1]
然后注意考虑清楚边界条件。

11. Container With Most Water
假设选择的柱子是i和j,那么题目就是要最大化loss = min(height[i], height[j])*(j-i)。
三种方法:
假设j是右柱,且是容器短板,那么要loss最大,就要找j左边的,比height[j]大的柱子i,且i离j最远,往左扫描一遍去找,算法整体复杂度O(n^2)。
有没有更快的方法呢?可以维护一个所有柱子高度为key,这个高度对应的最左边柱子的下标为value的列表,然后只需要在这个表中,二分查找最小的大于等于height[j]的那个柱子的下标即可,复杂度O(nlogn)。
上面两个方法都假设j是右柱且是短板,但有时可能是左柱是短板,处理方法是把输入反过来用函数再求一遍,取两者的较大值。
还能不能更快?要想loss最大, 可以先让j-i最大,即two pointers分别选最左和最右,但loss还取决于height,所以需要移动pointers,怎么移呢?有一点可以明确的是,two pointers中的高度小的那一个,一定不会再作为后面求最大值时的参考柱子,因为如果选它,后面容器的宽度会减小,而高度永远都不会大于这根柱子,所以loss永远不会变大。由此得到策略,移动two pointers中高度小的那个,如果两个一样怎么办?随便选哪个都可以。复杂度O(n)。

12. Integer to Roman
跳过

13. Roman to Integer
跳过

14. Longest Common Prefix
简单扫描。

15. 3Sum
当选定一个数之后,再选两个数就变成了2sum问题,对于排好序的数组,2sum问题是O(n)可以解决的,因此整体复杂度为O(n^2)。但是,题目要求去重,用set实现,复杂度O(n^2*logn^2),但实际答案数应该远小于n^2,所以还是很快的。

16. 3Sum Closest
和15几乎一样,不再赘述。

17. Letter Combinations of a Phone Number
python: itertools.product

18. 4Sum
多枚举一个元素,然后问题就变为3sum了,复杂度O(n^3)。有种做法,先预处理出两两之和,再枚举和二分查找,有人认为这种做法是O(n^2logn),实际不是。因为题目要求找到所有不同的解,所以不管解法是什么,答案最多有O(n^3)个,任何解法都绕不开这个下界。由这个问题,可以拓展到K-Sum问题,都是通过枚举不断规约,直到求2sum问题,复杂度O(n^k-1)。

19. Remove Nth Node From End of List
按描述写。

20. Valid Parentheses
栈模拟

21. Merge Two Sorted Lists
链表模拟。

22. Generate Parentheses
dfs。 注意,认为p(n) = ['()' + p(n-1), '('+p(n-1)+')', p(n-1)+'()'] 是错的,例如(())(())就不是,这种假设不要轻易断言。

23. Merge k Sorted Lists
依次一个一个Merge Two Sorted Lists,复杂度O(k^2),采用归并两两merge,复杂度降为O(klogk)。

24. Swap Nodes in Pairs
按描述写,注意head也变了。

25. Reverse Nodes in k-Group
还记得当年保研机试时用了一个半小时还是挂在了这道题上,重新再做,还是挂在了上面,用了一个下午才调出来,并且姿势极丑!。。。sad,以后有时间要再重做一次。

26. Remove Duplicates from Sorted Array
按描述写。

27. Remove Element
和上题一样。

28. Implement strStr()
KMP,不过和直接用python的index方法时间差别非常小。

29. Divide Two Integers
模拟除法,用类似快速幂的方法。

30. Substring with Concatenation of All Words

31. Next Permutation
这里定义的next permutation,是字典序比当前大1的排列,可以从整数加法的角度考虑,整数加法直接末位加1,然后进位就可以了。但这里因为能使用的数是有限的,末位想变大,只能从前面比它大的位交换过来,而这样的话,前面的位就会变小,那字典序反而减小了。所以只能考虑末位前面的,尽量靠近末位的位置(使字典序最小),用这个位置后面的某个比它大的数,来和它交换,然后令后面的所有数字从小到大排序。
数学上表示,假设i是要找的位置,那么要满足,nums[i] < max(nums[i+1:]), 并且在nums[i+1:]中,nums[k] > nums[k+1] ,所以就是从右往左找满足 nums[i] < nums[i+1] 的第一个位置。

32. Longest Valid Parentheses
two pointers方法,用cntl和cntr分别记录指针间左括号和右括号的个数,若左大于右,则右指针右移,因为以左指针为首的有效序列还可能更长,否则左指针右移,因为以左指针为首的序列,不可能再有更长的有效长度。当左右指针相同,左还需右移时,则两个指针同时右移。当左右括号个数相等时,可以更新最长长度。但这么做有一个没有考虑的情况,"(()",即左括号数一直比右多,答案就不会更新。解决方法是,再从右往左扫,并维护右括号大于等于左括号数的最长序列。

33. Search in Rotated Sorted Array
先二分找到翻转轴的位置,再正常二分查找即可。

34. Search for a Range
二分查找

35. Search Insert Position
二分查找

36. Valid Sudoku
按描述写

38. Count and Say
跳过

39. Combination Sum
完全背包,解法几乎和40题相同,不赘述。

40. Combination Sum II
0-1背包问题,要求输出答案,因为没给target范围,于是dp实现用了dfs搜索,字典记录状态(nb, rem) 是否有答案,即选择到第nb个物品,还剩rem容量,是否有可能达到。

41. First Missing Positive
不让用额外的内存,但可以用输入的那一块内存,想到这个剩下的就简单了。

42. Trapping Rain Water
每块trap water的特点是,设i,j分别为左右柱,则a[k]<min(a[i],a[j]) (i<k<j), 并且不存在x<i and y>j,使得a[k]<min(a[x],a[y]) (x<k<y)。 这样,由于第一个柱子一定是左柱,那只需要往右找直到出现比它高的柱子,再继续往右则不能满足前面的约束条件了。这样就找到了第一个trap area,然后以右柱作为新的左柱继续找。注意,[3,2,1,2,1]这种找不到比左柱高的情况,只需倒过来找一遍即可。

43. Multiply Strings
大整数乘法.

44. Wildcard Matching
类似10.

45. Jump Game II
开始想用记忆化搜索,爆栈了,查了一下,发现python最多递归1000层,改用bfs,超时,这时才发现自己把复杂度算错了,本以为O(n),实际上每次拓展的时候,用时可能是O(n)而不是O(1),所以复杂度O(n^2)。仔细考虑,其实只用维护一个目前能向右跳到的最远点,然后不断迭代更新这个值即可。

46. Permutations
生成全排列.

47. Permutations II
unique 全排列.

48. Rotate Image
原地顺时针旋转n*n矩阵90度.

49. Group Anagrams
按描述写.

50. Pow(x, n)
注意n为负的情况.

53. Maximum Subarray
最大子串和.

54. Spiral Matrix
矩阵蛇形输出.

55. Jump Game
类似45.

58. Length of Last Word
按描述写.

59. Spiral Matrix II
按描述写.

60. Permutation Sequence
第k个permutation可以直接算出来,不用一一枚举。假设当前序列长度为len,那么这个序列的第k个排列与tmp=factorial(length-1)有关。

61. Rotate List
维护三个指针。

62. Unique Paths
组合数公式

63. Unique Paths II
dp

64. Minimum Path Sum
dp

66. Plus One
模拟加法

67. Add Binary
二进制加法

68. Text Justification

69. Sqrt(x)
按描述写

70. Climbing Stairs
斐波那契数列

71. Simplify Path
按描述写

73. Set Matrix Zeroes
按描述写

74. Search a 2D Matrix
利用Matrix的数学性质,m[x][y] >= m[i][j] (i<=x and j<=y), m[x][y] <= m[i][j](i>=x and j>=y)。这样,可以根据矩阵的“中心”,把矩阵切分为四块,根据m[x][y]相对于target的大小,丢掉其中的一块,只在剩下的三块中寻找target。分治法,复杂度O(log(4/3, n))。
看了论坛后,发现读错题了,实际上问题只是上述问题的一种特殊情况,可以每次丢掉一半,复杂度O(log(2, n))。

75. Sort Colors
counting sort

77. Combinations
生成组合

78. Subsets
生成所有组合

79. Word Search
dfs

80. Remove Duplicates from Sorted Array II
按描述写

81. Search in Rotated Sorted Array II
先把相等的去掉,然后就等同于第33题了,复杂度变成O(n)。或者先找到“扭转点”,只能线性找,然后等同于33题,复杂度O(n)。

82. Remove Duplicates from Sorted List II
按描述写

83. Remove Duplicates from Sorted List
按描述写

86. Partition List
按描述写

88. Merge Sorted Array
按描述写

89. Gray Code
按描述写

90. Subsets II
按描述写

91. Decode Ways
简单dp

92. Reverse Linked List II
按描述写

93. Restore IP Addresses
因为ip地址较短,组合数比较少,直接枚举所有情况,但要注意长度大于12的就不要枚举了。

94. Binary Tree Inorder Traversal
非递归二叉树的中序遍历,栈模拟递归

95. Unique Binary Search Trees II


96. Unique Binary Search Trees
dp[i] 表示,用i个数字构建一棵合理的二叉排序树有多少种方法。dp[i] = sum(dp[j-1]*dp[i-j]) (1<=j<=i)

98. Validate Binary Search Tree
二叉排序树,所有数从小到大的排列顺序,应该是中序遍历的结果。判断一棵二叉排序树是否合法,等价于判断中序遍历的序列是否是从小到大排列的。

100. Same Tree
递归判断

101. Symmetric Tree
先得到层次遍历结果,然后判断

102. Binary Tree Level Order Traversal
层次遍历

103. Binary Tree Zigzag Level Order Traversal
按描述写

104. Maximum Depth of Binary Tree
按描述写

105. Construct Binary Tree from Preorder and Inorder Traversal

106. Construct Binary Tree from Inorder and Postorder Traversal

107. Binary Tree Level Order Traversal II
按描述写

108. Convert Sorted Array to Binary Search Tree

109. Convert Sorted List to Binary Search Tree

110. Balanced Binary Tree
按描述写

111. Minimum Depth of Binary Tree
bfs

112. Path Sum
按描述写

113. Path Sum II
按描述写

114. Flatten Binary Tree to Linked List
按描述写

116. Populating Next Right Pointers in Each Node
先得到level order,然后按描述写

118. Pascal's Triangle
按描述写

119. Pascal's Triangle II
杨辉三角第m行第n列,即二项式C(m-1,n-1)。

120. Triangle
滚动数组dp

121. Best Time to Buy and Sell Stock
维护left_min,left_min[i] 表示 i 及 i 左边最小值,right_max, right_max[i] 表示 i 右边最大值,然后找 right_max[i]-left_min[i] 最大值。

122. Best Time to Buy and Sell Stock II
贪心买卖

125. Valid Palindrome
按描述写

127. Word Ladder
bfs,很多解答用生成可能邻近词,来减少枚举数,这种方式,可以大大减少复杂度。

129. Sum Root to Leaf Numbers
按描述写

130. Surrounded Regions
bfs

131. Palindrome Partitioning
按描述写

133. Clone Graph
没看懂题意

134. Gas Station
two pointers

136. Single Number
每个数字都出现两次,除了一个数只出现一次,找到那个数。栈模拟可以解决,不过要用额外的空间。怎么才能不用呢?最好是所有相同的数都排在一起,这样把它们两两相消,就得到最后那个不同的数了,然而要排序的话,复杂度就不是线性了,而且依然需要额外的空间。怎么办?用一个很厉害的数学性质!亦或操作是满足交换律的!这样,把所有数字按位亦或,因为相同的数字亦或就都变成了0,这样最后的结果就是要找的那个数了。

137. Single Number II
k个数字出现3次,一个数字出现1次,这样把每个数按位相加,得到每位出现1的次数统计,这个次数一定是3*k+1 或者 3*k ,并且只有出现一次的数该位为1时,次数是3k+1,这样就得到了那个数。最后,千万注意不要忘了考虑这个数的正负性。

139. Word Break
dp

141. Linked List Cycle
把走过的链表反向,这样如果有环,最后会回到表头,不过这样破坏了链表的原有结构。
还有种方法,维护两个指针,一个每次走一步,一个每次走两步,这样如果有环,最终它们会碰到一起。相遇的时间,是环长度的倍数。

142. Linked List Cycle II
利用上题提到过的,相遇时间 t ,是环长度的倍数。这样只需要先得到相遇时间,然后维护两个指针,开始都指向头,再让一个指针后移t步,然后开始把两个指针一起往后移,它们第一次相遇的位置,一定是环的头。

143. Reorder List
按描述写

144. Binary Tree Preorder Traversal
按描述写

147. Insertion Sort List
按描述写

148. Sort List
按描述写

150. Evaluate Reverse Polish Notation
按描述写,python 整数除法,如果两个数符号不同,会出现和c运算不一致的结果,python是向负无穷方向取整,特别注意!

151. Reverse Words in a String
按描述写

152. Maximum Product Subarray
dp[i][0] 表示包含 nums[i]的最大连乘积,dp[i][1] 表示包含 nums[i]的最小连乘积,然后打表。另外注意,用预处理连乘积,来快速求任意一段的乘积,这个方法只适用于不包含0的数列。这道题要想利用这个预处理,然后O(n^2)枚举序列首尾,必须先把原数列,拆成不含0的子数列。

153. Find Minimum in Rotated Sorted Array
 Search in Rotated Sorted Array 的 简化版

155. Min Stack
按描述写

160. Intersection of Two Linked Lists
先求得两个链表的长度,然后把长的表头,向后移到和短的表离末端同样的距离,然后把它们俩同步向后移,若链表交叉,则一定会相遇。

162. Find Peak Element
二分搜索,观察 mid, mid+1, mid-1 的值,根据这三者的大小关系,移动指针。

165. Compare Version Numbers
按描述写

166. Fraction to Recurring Decimal
模拟除法。识别无限循环小数的方法是,记录已经用过的除数和它们的位置,如果发现重复出现,则说明开始有循环,根据重复出现的数的位置,得到循环开始的地方。

167. Two Sum II - Input array is sorted
two pointers

168. Excel Sheet Column Title
按描述写

169. Majority Element
扫一遍,字典计数是最直接的做法,不过这里还可以优化空间,用一个stack,当前值和stack顶端相同,则push,否则pop,最后stack里剩下的就是答案。原因是,直观理解,因为这里的众数数目大于一半,所以两两相消,那它一定是幸存者,而其他的互相残杀是更好。

171. Excel Sheet Column Number
按描述写

172. Factorial Trailing Zeroes
得到n!的某个质因数分解的最快方法是,分别计算这些数中,有多少个a的倍数,a^2的倍数,a^3的倍数。。。,这个质因数的个数,就是它们的和。

173. Binary Search Tree Iterator
用栈记录到达当前节点的路径。

179. Largest Number
关键是定义清楚任意两个数字它们排放时的相对顺序。按字典序比较s1+s2 和 s2+s1的大小,另外注意结果为多个0的情况。

187. Repeated DNA Sequences
用一个字典记录所有长度为10的子串出现的次数,取次数大于1的,复杂度O(10*n*logn)。

189. Rotate Array
按描述写

190. Reverse Bits
按描述写

191. Number of 1 Bits
按描述写

198. House Robber
dp

199. Binary Tree Right Side View
按描述写

200. Number of Islands
flood fill

201. Bitwise AND of Numbers Range
找规律。假设2**k <= n < 2**(k+1), if m < 2**k: return 0; else: 2**k + (m-2**k, n-2**k) 子问题的答案。

202. Happy Number
按描述写

203. Remove Linked List Elements
按描述写

204. Count Primes
素数筛法

205. Isomorphic Strings

 按描述写

206. Reverse Linked List
按描述写

207. Course Schedule
判断一个有向图是否有环。拓扑排序。

208. Implement Trie (Prefix Tree)
字典树

209. Minimum Size Subarray Sum
two pointers, O(n),预处理前缀和,然后二分搜索,O(nlogn)

210. Course Schedule II
拓扑排序

211. Add and Search Word - Data structure design
查询一个字符串在不在给定的库中,字符串中可以含有通配符。

两种方法:
1 建二叉平衡搜索树。正常建树,大小的比较用字典序。搜索的时候,无通配符的还是正常搜索,有通配符的怎么办呢?比较的时候,先看是否相等,不等的话,再看能不能比较出字典序大小,如果遇到通配符还没比出来,那么左右两支都要搜索。
没有通配符的插入和查询复杂度是O(len_str * logn), n是库的大小,len_str 是字符串的长度。有的话,无法估计,最差是O(len_str * n)。
2 建字典树。正常建树,搜索的时候,无通配符的正常搜索,有的话,需要枚举当前节点下所有子树。没有通配符的插入和查询复杂度是O(len_str), 有的话,最差是O(len_str * n)。

比较1和2的两种方法,会发现,字典树一定比二叉平衡搜索树优,而且字典树的空间复杂度也会较小。所以,对于这类字符串在库中的查找问题,建议使用字典树。

213. House Robber II
分类讨论,rob第0间房,或者不rob第0间房,不论怎样,就都不是环了,问题划归为 198.House Robber

215. Kth Largest Element in an Array
第k大数。用快排的思想写,复杂度是O(n)。

216. Combination Sum III
枚举组合

217. Contains Duplicate
按描述写

219. Contains Duplicate II
用一个字典记路下所有数字对应的位置,然后枚举相同数字的位置,检查差值。

220. Contains Duplicate III
维护两个单调队列,可以O(1)求区间长度为k的最大值和最小值,然后从左向右扫描即可。

221. Maximal Square
dp

222. Count Complete Tree Nodes
二分搜索,找最后一层的叶子节点最右边是哪里。

223. Rectangle Area
求两个矩形交的面积。

225. Implement Stack using Queues
按描述写

226. Invert Binary Tree
这就是当时 Max Howell 被google拒掉的一题?“ Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.”
这么简单都不会做,要是我也不要他。

227. Basic Calculator II
直接eval不行,表达式太长时会出问题,栈模拟

228. Summary Ranges
按描述写

229. Majority Element II
哈希表

230. Kth Smallest Element in a BST
dfs

231. Power of Two
n & (n-1)

232. Implement Queue using Stacks
按描述写

234. Palindrome Linked List
按描述写,要space O(1),就修改list的指向即可。

235. Lowest Common Ancestor of a Binary Search Tree
按描述写

236. Lowest Common Ancestor of a Binary Tree
LCA

237. Delete Node in a Linked List
因为无法拿到当前节点的前一个,所以只能让前一个点继续指向它,然而把它修改成后一个点即可,再删掉后一个点。

238. Product of Array Except Self
所谓不用额外空间,就是先把要记录的记在ret空间里。

240. Search a 2D Matrix II
同74

241. Different Ways to Add Parentheses
按描述写

242. Valid Anagram
按描述写

257. Binary Tree Paths
dfs

258. Add Digits
按描述写

260. Single Number III
这题要求用常数空间,且又有多个偶数对,这类题首先就考虑按位加。加出来的结果中,一定有至少一位的和是奇数,这样找到所有这一位是奇数的数,它们中一定只包含一个只出现一次的,和若干对出现两次的。

然后问题就转化成了136。注意正负数要分开计数!

263. Ugly Number
按描述写

264. Ugly Number II
两种方法:
1 类似筛法,需要筛的范围很小。
2 dp。假设已知ugly numbers 有 a1,a2 ... ak,ak+1 一定由x,y,z(属于 a1~ak) ,min(x*2, y*3, z*5) 得到。那怎么去找x, y, z呢?可以暴力从a1~ak中去找,也可以dp维护,假设x 是 ai,那么下一个x,一定是ai+1。
DP方法更值得推荐!

268. Missing Number
0~n的和减去输入数的和一定是缺失的那个数。

274. H-Index
因为H的范围是0~len(citations), 用计数排序,大于len(citations)的,归到len(citations),然后问题变成了275.

275. H-Index II
二分搜索

278. First Bad Version
二分搜索

279. Perfect Squares
多重背包

283. Move Zeroes
按描述写

284. Peeking Iterator
peek,需要deepcopy iterator

289. Game of Life
按描述写

290. Word Pattern
一一映射

292. Nim Game
4的倍数,输

299. Bulls and Cows
实在看不懂题意

300. Longest Increasing Subsequence
最长上升子序列

303. Range Sum Query - Immutable
前缀和

304. Range Sum Query 2D - Immutable
前缀和

306. Additive Number
dfs

307. Range Sum Query - Mutable
线段树

309. Best Time to Buy and Sell Stock with Cooldown
dp,当天卖了和没有卖的最大值,再记录一个到当前为止,买了一个物品在手的最大收益。

310. Minimum Height Trees
猜想树的中心最多只有两个,找到直径长度后,再找中心

313. Super Ugly Number
类似264,但要加优先队列

318. Maximum Product of Word Lengths
按描述写,O(n^2)。这里有一个技巧,找一个集合是否与另一个集合有交集,当集合size小于32或64时,可以用一个整数编码,用位运算快速判断。

319. Bulb Switcher
找规律,发现约数个数是2的倍数的,一定是off,不是倍数的,是on。哪些不是2的倍数呢?完全平方数。

322. Coin Change
dp

324. Wiggle Sort II
先用求第k大数的方法找到中位数,然后把小于中位数的数字放在奇数位,并且是从后忘前放,
大于中位数的数字放在偶数位,从前往后放,剩下的位置放等于中位数的数字。
注意这个题目中等于中位数的坑!
两个步骤的复杂度都是O(n),所以总体算法复杂度也是O(n)。

326. Power of Three
按描述写

328. Odd Even Linked List
维护两条链,奇数链和偶数链,最后再把它们连起来。

331. Verify Preorder Serialization of a Binary Tree
栈模拟。不合理的序列是,树应当已经被遍历完了,序列还没结束。

332. Reconstruct Itinerary
找欧拉路

334. Increasing Triplet Subsequence
最长上升子序列的简化版,维护长度为1的最小值,和上升长度为2的最小值。

337. House Robber III
树形dp

338. Counting Bits
找规律

341. Flatten Nested List Iterator
按描述写

342. Power of Four
注意2和4的区别。

343. Integer Break
dp,或者找规律。

344. Reverse String
按描述写。

345. Reverse Vowels of a String
按描述写

347. Top K Frequent Elements
先计数,dict计数,O(n). 然后用heapq,选择前k大,O(nlogK).

349. Intersection of Two Arrays
按描述写

350. Intersection of Two Arrays II
按描述写

355. Design Twitter
按描述写

357. Count Numbers with Unique Digits
排列数

365. Water and Jug Problem
记忆化搜索,复杂度还是太高,有数学性质。

367. Valid Perfect Square
二分

368. Largest Divisible Subset
如果当成最大团问题来解,那就复杂了,NPC问题。
但是因为这个问题的特殊性,最终要求的序列,假设把它从小到大排序,那么只要满足,前一个数是后一个数的约数即可。于是先排序,然后dp,复杂度O(n^2)。

371. Sum of Two Integers
sum函数,本意上让人用位运算。

372. Super Pow
找循环节

373. Find K Pairs with Smallest Sums
优先队列

374. Guess Number Higher or Lower
二分搜索

375. Guess Number Higher or Lower II
dp

376. Wiggle Subsequence
dp,或者贪心,贪心假设的正确性只是猜测,没有严格证明。

377. Combination Sum IV
dp

378. Kth Smallest Element in a Sorted Matrix
利用矩阵的性质,用优先队列维护一个可能是最小值的队列,然后不停找最小的,直到第k个。
复杂度O(k*log(n))

382. Linked List Random Node
流数据采样的算法。

383. Ransom Note
按描述写

384. Shuffle an Array
按描述写

385. Mini Parser
按描述写

386. Lexicographical Numbers

387. First Unique Character in a String
按描述写

388. Longest Absolute File Path

389. Find the Difference
按描述写

390. Elimination Game
直接模拟不行,即使只是O(n)复杂度也超时了。仔细研究模拟部分,其实每次不需要把所有值都复制一遍,而只需要知道下一轮剩下的数中,起始数字的位置,而移动的步数都是之前的两倍。起始数字的位置,分情况讨论就好了。复杂度O(logn)

392. Is Subsequence
维护两个指针,贪心即可。但对于follow up question,每次还是这么贪心,复杂度就显得太高了O(t)。实际上,因为字的范围只有小写英文字母,我们可以先记录下所有字母在母串t中出现的位置,这样每次在贪心找下一个匹配位置的时候,就不用线性扫描过去了,而是可以在记录位置的数组中,二分查找,复杂度降为O(s*logt)。

393. UTF-8 Validation

394. Decode String
画个状态机,然后按照状态机模拟。

395. Longest Substring with At Least K Repeating Characters
先预处理一个前缀和,然后O(n^2)枚举所有可能情况看是否符合。超时了。。。
考虑优化,找每个以i结尾的最长子串时,实际上不用一一枚举过去,先检查一直到最左边是否可以,如果不可以,找到那些不可以的,把它们全部“删掉”,然后再检查删掉之后的串是否合理,不合理继续删。由于每次删的过程,移动的步数可能远大于1,因此复杂度是会低于O(n^2)的。删的过程,可以用二分查找,类似392,先预处理出每个字母出现的位置,然后二分找小于等于i的最大位置。

396. Rotate Function
枚举所有情况,一共就n种。每种求和的时候,如果一一算,就又需要O(n)的时间,那么总的就是O(n^2)。实际上,可以利用上一次的计算结果,做到O(1), 这样总的复杂度是O(n)。

397. Integer Replacement
bfs

398. Random Pick Index
Reservoir Sampling,对于第i个target,1/i的概率抛掉之前的位置,选择当前的位置。

400. Nth Digit
按描述写

401. Binary Watch
按描述写

402. Remove K Digits
贪心删除,保留最高位最小,最后如果还有剩余的删除数,就从后往前删。

404. Sum of Left Leaves
dfs

405. Convert a Number to Hexadecimal
按描述写

406. Queue Reconstruction by Height
依次考虑从前往后的排序,第一个人是什么呢?它前面比它高的人数一定是0,但是如果有多个是0的怎么办呢,只能选择高度最小的那个,否则它放到后面永远都无法满足,前面比它高的人数是0.那第二个人是什么呢,因为已经放了一个人,那么后面所有比他矮的,且前面需要放一个人的那些人,现在也都可以放了,同理,放高度最小的那个。
于是,算法就出来了,每次放前面人数为0的高度最小的,然后把所有高度小于等于他的,前面的人数减一,依次进行下去。总体复杂度O(n^2)。

409. Longest Palindrome
按描述写

52. N-Queens II
打表

287. Find the Duplicate Number
不让修改原数组,不能排序。不让用额外空间,不能用hash表计数,不能O(n^2),不让暴力枚举。数可重复出现多次,而不是只有两次,不能用亦或的性质解这题。
怎么办呢?考虑O(nlogn), 怎么二分?利用数的范围只有1~n这个性质,假设这个数是mid,那么在数组中,mid~n的数目一定大于n-mid+1的数目。利用这个性质不断二分可以找到答案。

312. Burst Balloons
这题想了很久。开始想枚举第一个烧掉的气球,但发现左右子问题之间会互相影响,没法dp。。。然后,在花了几个小时,尝试各种贪心,dp思路之后,终于推理到,可以枚举最后一个烧掉的气球,这样左右子问题不会互相影响,且最后烧掉的那个球的bonus也是已知的,这样O(n^3)算法就出来了。

352. Data Stream as Disjoint Intervals

145. Binary Tree Postorder Traversal
按描述写

399. Evaluate Division
要求任何两个变量的商,如果存在,那么它们一定有某条链串起来。于是,想到构建一副有向图,这个图的点,代表变量,两点的边,代表a除以b的值。那么要求x除以y的值,即x到y的路径的连乘积。如果输入没有给出两点的商,那么先设为空。剩下的问题就是,利用求可达矩阵的算法,求出所有可达的两点的商。然后利用最后这个距离矩阵,应对查询。


415. Add Strings
按描述写

416. Partition Equal Subset Sum
目标为和的一半的01背包

380. Insert Delete GetRandom O(1)
用一个hash表记录所有insert的值得位置,删除的时候,把最后一个放到它的位置上。

154. Find Minimum in Rotated Sorted Array II
类似81

128. Longest Consecutive Sequence
不考虑要求的话,肯定是先排序,然后找。现在要求O(n), 就不能排序了。像这种涉及到集合合并和查询的,用并查集是最合适的了。

329. Longest Increasing Path in a Matrix
记忆化搜索

301. Remove Invalid Parentheses

407. Trapping Rain Water II

117. Populating Next Right Pointers in Each Node II
按描述写

315. Count of Smaller Numbers After Self
线段树。从右往左,单点更新,区间查询。因为数的范围太大,所以需要先做一个离散化。每次修改和查询复杂度都是O(logn), 执行n次,总复杂度O(nlogn)。

419. Battleships in a Board
根据题意,每个连通块都是一艘飞船,所以只需要找连通块的个数。不让用额外的空间,那就不用,可以只看每个点的左边和上边,判断它是否是一艘飞船的“头”。

463. Island Perimeter
按描述写。

412. Fizz Buzz
按描述写

413. Arithmetic Slices
找到所有最长的递增子序列,然后按题意求和即可。

455. Assign Cookies
贪心,最大匹配。

462. Minimum Moves to Equal Array Elements II
最小化loss = sum(|a[i]-k|), i~(1,N),这个值是随k先单调递减,再单调递增,可以二分搜索k,算loss的时候,处理前缀和,然后二分搜索。复杂度,O(logINT * logN) + O(nlogn) = O(nlogn).

453. Minimum Moves to Equal Array Elements
数学找规律。答案是sum(nums) - len(nums)*min(nums)

459. Repeated Substring Pattern
枚举所有可能的子串长度

447. Number of Boomerangs
枚举一条边,另一条边也枚举复杂度太高,可以先预处理出所有以a为中心点,距离为d的点对有多少。

423. Reconstruct Original Digits from English
通过简单探索,可以发现有些字母,如w、u、x、g是“特别”的,它们只对应一种数字,那么就可以先把这些数字拿出来,排除这些数字后,再从剩下的当中,继续找“特别”的字母,反复迭代这个过程即可。

452. Minimum Number of Arrows to Burst Balloons
贪心

436. Find Right Interval
按区间起点排序,然后二分查找区间终点即可。

454. 4Sum II
预处理两两和,hash。

424. Longest Repeating Character Replacement

435. Non-overlapping Intervals
类似452,贪心。

421. Maximum XOR of Two Numbers in an Array

437. Path Sum III
枚举树上的所有可能情况。注意,没法贪心,因为有负值。

441. Arranging Coins
二分。

421. Maximum XOR of Two Numbers in an Array

424. Longest Repeating Character Replacement

438. Find All Anagrams in a String
滑动窗口计数即可。

417. Pacific Atlantic Water Flow
快速判断一个点能否走到最外的四条边,先用bfs预处理。

363. Max Sum of Rectangle No Larger Than K

354. Russian Doll Envelopes

330. Patching Array

297. Serialize and Deserialize Binary Tree
设计数据结构。

239. Sliding Window Maximum
单调队列

115. Distinct Subsequences
dp

72. Edit Distance
dp

410. Split Array Largest Sum
数组非负,可以贪心,最大最小,二分即可。

403. Frog Jump
bfs














2 0
原创粉丝点击