1. String
13.Implement strStr()
KMP算法
171.Anagrams
对之前代码对改进:
item_ = str(sorted(item))
注意要转换成string,因为list不能作为dictionary对hash表的key。
79. Longest Common Substring
再看一次还是没有思路,·
自己之前是用暴力做的。
但是现在看起来是一个典型的DP问题。
但是没想太好状态是怎么转变的-> 很简单。自己想多了。
78. Longest Common Prefix
可以用二分。但是蛮复杂的感觉不是很有必要。
2. Integer Array
78. Longest Common Prefix 游标x2/交换
记得python可以直接pop(index)
还有一种思路,是类似于快排的方法。
将相等的数置换到队尾,因为最后inplace的结果,只看前面
138. Subarray Sum 前缀和数组
想用list的index,但是好像不太好用的样子。
100. Remove Duplicates from Sorted Array 游标/交换
直接用list.pop(index)
其他人的做法,有一个游标,用来找到下一个和当前位置不等的数,并将这个数与当前位置的数进行交换
64. Merge Sorted Array 游标
队尾两个游标,从A, B中选取较大的一次填充到队尾
56. Two Sum hash表
50. Product of Array Exclude Itself 前缀积和后缀积,相乘
189. First Missing Positive 交换
将索引和数字匹配
59. 3Sum Closest 游标
固定最左边,left起始位置在固定点的相邻左侧,right在最右边
固定点从左到右移动。
15.3Sum
类似于上一题
3. Binary Search
141. Sqrt(x)
60. Search Insert Position
28. Search a 2D Matrix
把二维数组展开,用二分法,然后重写换算成二维数组的形式。
14. First Position of Target
159. Find Minimum in Rotated Sorted Array
很简单,只要找到第一个不是递增的就是了。
75. Find Peak Element
注意边界情况(然而边界情况被题目排出了,就比较好算)
74. First Bad Version
也是用二分法来找,但是我一开始还费劲吧啦地讨论前一个是false,后一个是true才是满足条件。后来看发现只需要是false右移,是true左移,最后l==r的时候,这个数就是结果。
62. Search in Rotated Sorted Array
分情况讨论,
61. Search for a Range
分两个二分法查找
183. Wood Cut
选取最大的木头,二分查找所有可能的情况,得到第一个可以的
4. Math & Bit Manipulation
181. Flip Bits 负数
负数处理方法:
ff = pow(2, 32)
a_r = (a+ff)%ff
142. O(1) Check Power of 2 **
这个做法也太巧妙了吧!利用了2的幂在二进制条件下的特殊形式。
由此可以推广到n进制(?
2. Trailing Zeros
只需要考虑5的情况,每个5都能产生一位0
179. Update Bits
163. Unique Binary Search Trees
递归
140. Fast Power
只需要考虑不整整除的部分,在每一次幂运算后的变化
180. Binary Representation
这道题要注意小数运算的问题
字符转化成浮点数
5. Greedy
82. Single Number 利用了异或两两抵消
所有元素与0异或,最后的结果是缺少的元素
46. Majority Element
O(nlogn)的话,可以先sort,再求二分之一
如果是O(n)的情况,可以利用主元素的性质,遍历每个元素,存储第一个元素,并与后面的元素比较,如果该元素等于存储的元素,count+1,否则减1,并将存储的元素替换为当前元素。最终留下的元素肯定是主元素。
187. Gas Station
因为是循环,所以可以计算从第一个开始,到最后一个的情况,然后找一个最低的位置,以他后一个开始。因为他们的相对情况是不变的。
184. Largest Number
182. Delete Digits
数学关系
- 每次操作都争取找最小的数
- 对每次找数时,应该删掉第一个比后面的数大的,因为前一位有进制的加成,肯定比后面的好。
116. Jump Game
每到一个位置,查看该位置是否可抵达,确认后更新后面的位置是否可抵达。
52. Next Permutation
- 将数列分成前后两端,保证后面是递减数列。
- 在后段从右往左,找到一个大于前段最后一个数的数(即后段第一个小于前段最后一个数的数)
- 将这个数和前段的交换。(此时后段递减的性质不变)
- 调整后段顺序,从递减到递增。
# num[:i+1] // num[i+1:] decrease
# find a smallest element which is bigger than num[i] -> num[j]
# num[:i] unchange
# num[i] <-> num[j]
#num[i+1:j] num[j] num[j+1:] decrease
# resvere
# num[i + 1 + k] <-> num[len(num) - 1- k]
# 0 - (len(num) - i)//
6. Linked List
174. Remove Nth Node From End of List 快慢指针
165. Merge Two Sorted Lists 建立新的linked list
新建的头结点只作为一个位置,没有实际意义,最后return的时候记得return newhead.next
112. Remove Duplicates from Sorted List 快慢指针
记得一直往后移动
96. Partition List
建立新的两个linked list 一个存大于的一个存小的。注意最后队尾一定要tail.next = null 否则可能残留。
=> 只建一个list
35. Reverse Linked List
搞清关系就好了,画图
170. Rotate List
- 注意关系
- count链表长度减少计算
106. Convert Sorted List to Binary Search Tree
特别巧妙的一个方式,dfs将时间复杂度降低到了O(n)
105. Copy List with Random Pointer
"""
Definition for singly-linked list with a random pointer.
class RandomListNode:
def __init__(self, x):
self.label = x
self.next = None
self.random = None
"""
class Solution:
# @param head: A RandomListNode
# @return: A RandomListNode
def copyRandomList(self, head):
# write your code here
dic = collections.defaultdict(lambda: RandomListNode(0))
dic[None] = None
pos = head
while(pos):
dic[pos].label = pos.label
dic[pos].next = dic[pos.next]
dic[pos].random = dic[pos.random]
pos = pos.next
return dic[head]
102. Linked List Cycle
快慢指针
99. Reorder List
翻转加插空
98. Sort List
7. Binary Tree
97. Maximum Depth of Binary Tree DFS
1+ max(左子树,右子树) if root else 0
特别简洁
93. Balanced Binary Tree
上面的升级版,用-1表示非的情况
85. Insert Node in a Binary Search Tree
不要求平衡,所以可以直接插入
69. Binary Tree Level Order Traversal
同样是是dfs增加了一个h
66. Binary Tree Preorder Traversal
preorder root -> left -> right
inorder left->root-> right
postorder left -> right -> root
95. Validate Binary Search Tree inorder
https://www.jiuzhang.com/solution/validate-binary-search-tree/#tag-highlight-lang-python
def isValidBST(self, root):
self.lastVal = None
self.isBST = True
self.validate(root)
return self.isBST
def validate(self, root):
if root is None:
return
self.validate(root.left)
if self.lastVal is not None and self.lastVal >= root.val:
self.isBST = False
return
self.lastVal = root.val
self.validate(root.right)
73. Construct Binary Tree from Preorder and Inorder Traversal
中序是按根结点的顺序,所以可以用来分割前序。
11. Search Range in Binary Search Tree
前序遍历
7. Serialize and Deserialize Binary Tree
中序遍历,不存在的点用#代替
class Solution:
def serialize(self, root):
def doit(node):
if node:
vals.append(str(node.val))
doit(node.left)
doit(node.right)
else:
vals.append('#')
vals = []
doit(root)
print(' '.join(vals))
return ' '.join(vals)
def deserialize(self, data):
def doit():
val = next(vals)
if val == '#':
return None
node = TreeNode(int(val))
node.left = doit()
node.right = doit()
return node
vals = iter(data.split())
return doit()
87. Remove Node in Binary Search Tree
找到左子树的最后一个结点作为根结点
左子树的处理方式为递归
8. Search & Recursion
152. Combinations
二叉树,每个数字放与不放
135. Combination Sum
放与不放
因为可重复,所以切记考虑
127. Topological Sorting 队列
统计入度,用字典存
当入度为0时,可以作为起始点
33. N-Queens DFS/BFS
我自己喜欢用bfs+队列
18. Subsets II
DFS
也可以看数字找规律
17. Subsets
上面的建议版本,不考虑重复
16. Permutations II
可以用非递归/递归的bfs和dfs来做
15. Permutations
没有重复的数,更简单
9 Dynamic Programming
115. Unique Paths II
动态规划,有障碍处置为0
111. Climbing Stairs
经典动态规划题
41. Maximum Subarray
当前面的子数列和大于0时,值得相加,否则重新开始一个子数列
191. Maximum Product Subarray
记录当前位置下,最大和最小(负数的绝对值最大)的情况
119. Edit Distance
分析好增删改分别对应dp的不同状态即可
118. Distinct Subsequences
分析具体过程,可以得到,t从左到右,依次找,看是否在左边找完的情况下,在右边找到剩下的部分
109. Triangle
从下往上分析更好,O(n)空间复杂度
107. Word Break
和118分析方式类似
92. Backpack
动态规划的转移方程:
for j in range(1, m + 1):
if j >= A[i - 1]: #背包比这个物品大,则不放这个物品,是否可以达到j或者放了能否达到j
f[i][j] = f[i - 1][j] or f[i - 1][j - A[i - 1]]
else: #不放是否能达到j
f[i][j] = f[i - 1][j]
10. Data Structure
124. Longest Consecutive Sequence
利用hash表,得到它两边的的元素,更新它们的边界。
104. Merge K Sorted Lists
使用heapq构建一个头结点的最小堆,保证最小堆中每个元素均为各个数组中最小的数
40. Implement Queue by Two Stacks
stack1 压入,则先将stack中所有的数pop+push到stack2,再pop+push到stack1
12. Min Stack
记录当前最小值(不需要pop出最小值
4. Ugly Number II
保证比之后小的数都压入了res中
三个游标分别表示res中2,3,5分别乘到哪一个数了
面对此类最小的问题,又是顺序,可以考虑多个游标进行比较
132. Word Search II
Tire构造
trie = {} #4339361904
for w in words:
#print(trie)
t = trie #4339361904
#print(id(t),id(trie))
for c in w:
if c not in t: #不存在相同前缀的单词已在字典树
t[c] = {} #t:4339361904 #t[c]: 4339361976
print(id(t),t)
t = t[c] #t:4339361976
print(id(t),t)
print("*****")
t['#'] = '#'
print(id(trie))
深度优先
记得每个分支之间互不影响所以要把状态改回来
122. Largest Rectangle in Histogram
单调栈
栈记录着index都是单调的
class Solution:
"""
@param height: A list of integer
@return: The area of largest rectangle in the histogram
"""
def largestRectangleArea(self, height):
# write your code here
l = len(height)
if l == 0:
return 0
max_size = 0
monos = []
res = [0 for _ in range(l)]
for i in range(l):
while(len(monos) != 0 and height[monos[-1]] >= height[i]):
max_size = max((i - monos[-1] + res[monos[-1]]) * height[monos[-1]], max_size) # å¯ä»¥å®ƒä¸ºé¡¶çš„æœ€å¤§çŸ©å½¢çš„æƒ
况
res[i] = i - monos[-1] + res[monos[-1]] #å¯ä»¥å®ƒä¸ºé¡¶çš„æœ€å¤§çŸ©å½¢çš„æƒ
况
monos.pop()
monos.append(i)
while(len(monos)):
max_size = max((l - monos[-1] + res[monos[-1]])*height[monos[-1]],max_size)
monos.pop()
return max_size
# 没考虑到想到相ç‰çš„æƒ
况```
### 81. Find Median from Data Stream
最大堆和最小堆,一边大一边小
代码tricks很巧妙
```python
from heapq import *
class Solution:
"""
@param nums: A list of integers
@return: the median of numbers
"""
def medianII(self, nums):
# write your code here
small, large, res = [], [], []
for num in nums:
heappush(small, -heappushpop(large, num))
if len(large) < len(small):
heappush(large, -heappop(small))
if len(small):
if len(large) == len(small):
res.append(-small[0])
else:
res.append(large[0])
else:
res.append(num)
return res