12月以来有点忙,而目测得忙到12月中,之间抽空写了几道,计算天数已经没什么意义了,就这样吧。
本来打算先到200的时候,暂缓一段时间,等忙完再开始,现在是197道,但是题号已经到300多了……中间锁住的还有很多SQL相关的。
文章目录
331. Verify Preorder Serialization of a Binary Tree
对于一棵树来说,我们可以用前序遍历来写出它的所有元素,对于空值我们用#
来表示,现在给定一个前序的顺序,判断能不能组成一棵树。
像上图中的例子,我们就可以表示为[9,3,4,#,#,1,#,#,2,#,6,#,#]
关于这题,我们可以用栈的想法去做。
以上面的二叉树为例:
我们定义一个栈,stack = []
然后开始遍历前序顺序,把元素不断的压入栈
[9,3,4,#]
,这时候要压入的元素是#
,栈顶的也是#
,我们弹出前面的两个元素,然后再压入一个#
。这就相当于将原来的一个二叉树子树用#
代替了,然后我们栈内的元素为[9,3,#]
按照这个规则然后继续[9,3,#,1]
→
\to
→ [9,3,#,1,#]
→
\to
→ [9,3,#,#]
→
\to
→ [9,#]
→
\to
→ [9,#,2]
→
\to
→[9,#,2,#]
→
\to
→[9,#,2,#,6]
→
\to
→[9,#,2,#,5,#]
→
\to
→ [9,#,2,#,#]
→
\to
→ [9,#,#]
→
\to
→[#]
而且剩下的是[#]
,而且这时候前序顺序也遍历完毕,如果[#]
出现在前面的话,那么就说明这个序列不正确,或者最后剩下的不是[#]
那么再次仔细观察我们的序列,其实我们真正关心的不是序列内的值,而是序列内#
的个数以及非#
的个数,当遇到#
的时候-1
,遇到普通数字的时候+1
,#
的数量比数字的个数要多一个,因此如果初始值是1的话,最后应该是0,而且中间不能出现0,也就是对应上面[#]
的情况。
所以我们最后的代码为:
class Solution(object):
def isValidSerialization(self, preorder):
"""
:type preorder: str
:rtype: bool
"""
nodes = preorder.split(',')
num = 1
for node in predorder:
if node == '#':
num-=1
else:
num+=1
if num ==1:
return False
return num==0
332. Reconstruct Itinerary
给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 出发。
说明:
如果存在多种有效的行程,你可以按字符自然排序返回最小的行程组合。例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前
所有的机场都用三个大写字母表示(机场代码)。
假定所有机票至少存在一种合理的行程。
示例 1:
输入: [[“MUC”, “LHR”], [“JFK”, “MUC”], [“SFO”, “SJC”], [“LHR”, “SFO”]]
输出: [“JFK”, “MUC”, “LHR”, “SFO”, “SJC”]
示例 2:
输入: [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出: [“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解释: 另一种有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”]。但是它自然排序更大更靠后。
中文题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-itinerary
这里需要强调的有几点,而搞明白其中的这几点对于我们做出这道题有着很大的帮助。
- 其中出现奇数次的机场肯定是起点(JFK)或者是终点
- 如果没有奇数点,此时起点和终点是一个点,此时可以顺利的从从起点到终点走完。
- 我们可能会提前遇到终点从而出现阻塞。
因此,堵塞的时候,就是遇到终点的时候,我们将到终点的这条路径储存到route中,然后往前回溯寻找下一个条路。
代码
class Solution(object):
def findItinerary(self, tickets):
"""
:type tickets: List[List[str]]
:rtype: List[str]
"""
dict_travel = {}
for s,a in sorted(tickets)[::-1]:
dict_travel[s] = dict_travel.get(s, [])+[a]
route, stack = [],['JFK']
while stack:
while dict_travel.has_key(stack[-1]) and dict_travel[stack[-1]]:
stack.append(dict_travel[stack[-1]].pop())
route.append(stack.pop())
return route[::-1]
334. Increasing Triplet Subsequence
判断一个数列中有没有递增的三个数。
很简单,我们存下最小的和最大的数 ,判断没有有比他们更大的就行了。
代码如下:
class Solution(object):
def increasingTriplet(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
first = second = float('inf')
for i in nums:
if i <= first:
first = i
elif i <= second:
second = i
else:
return True
return False
337. House Robber III
解法可以看这里
这是我在Leetcode上暂时见过最好的回答。
代码如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
res = self.subrob(root)
return max(res)
def subrob(self, root):
if not root:
return [0,0]
left = self.subrob(root.left)
right = self.subrob(root.right)
res = [0, 0]
res[1] = root.val + left[0] + right[0]
res[0] = max(left[0], left[1]) + max(right[0], right[1])
return res
343. Integer Break
将一个数拆成至少两个正整数,求这几个正整数的最大乘积。
其实只要拆成2和3就就可以了。4=2*2,5<3*2
代码如下:
class Solution(object):
def integerBreak(self, n):
"""
:type n: int
:rtype: int
"""
if n<=3:
return n-1
if n%3==0:
return pow(3, n//3)
if n%3==1:
return pow(3, n//3-1)*4
if n%3==2:
return pow(3,n//3)*2
347. Top K Frequent Elements
返回一个数列出现次数在第k多以前的数。
用哈希表的话就很简单了。
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
dic = {}
for i in nums:
dic[i] = dic.get(i,0)+1
arr = sorted(dic, key = dic.get)[::-1]
return arr[:k]